Понимание функций стрелок на примере - PullRequest
0 голосов
/ 25 апреля 2018

У меня проблемы с пониманием решения проблемы кодирования, в которой используются функции стрелок и метод .every (), и я надеялся, что кто-то более знающий сможет объяснить, что происходит. Задача состоит в том, чтобы проверить сетку, чтобы увидеть, представляет ли она истинную доску судоку. Я понимаю, что первая часть объединяет и умножает строку / столбец / квадрат, но не может понять последнюю часть ...

// True, if product of #s in row is 9!
p = a => eval(a.join("*")) == (1*2*3*4*5*6*7*8*9);

// Check each row, column and 3 block grid using p() 
sudoku = grid => 
  grid.every((r,i) =>
    p(r) &&
    p(grid.map(r => r[i])) &&
    p(r.map((_,j) => grid[3*(i/3|0)+(j/3|0)][3*(i%3)+(j%3)]) ) )

Спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

По большей части функция стрелки - это просто функция.Единственное различие между ними состоит в том, что this сохраняется из внешнего контекста при использовании функции стрелки, тогда как this - это this, который использовался для вызова функции с нормальной функцией.

function A() {
  this.v = 1;
  this.a = () => console.log(this.v);
  this.b = function () { console.log(this.v) };
}

// Both will use `obj` as `this`
const obj = new A();
obj.a();
obj.b();

// The arrow-function `a()` will keep the same `this` as above, `obj` will change.
const obj2 = { v: 2 };
obj2.a = obj.a;
obj2.b = obj.b;
obj2.a();
obj2.b();

Другое отличие, которое может вас оттолкнуть, заключается в функции стрелки, если требуется только одна строка, вы можете опустить фигурные скобки ({}) ион вернет значение.То есть,

a => 1

То же самое, что и

function (a) { return 1; }

В этом примере кода функция стрелки или обычная функция не изменилась бы, поскольку this невызывается.

Код выполняет следующие действия:

grid.every((r, i) =>

Просматривает каждый элемент в grid и продолжает работать до тех пор, пока он не вернет true.r - текущее значение grid, а i - текущий индекс, который он обрабатывает.

grid.map(r => r[i])

буквально просто получает значение i-th из r и возвращает его.Это было бы для проверки диагоналей двумерного массива.(Таким образом, он получает grid[0][0], grid[1][1] и т. Д.).

r.map((_, j) => grid[math])

Затем просто перебирает каждый элемент в r и получает некоторый элемент (на основе этой математики), используятекущий i индекс от внешнего контура и j индекс от r.Использование _ в качестве имени параметра является общепринятым соглашением, указывающим на то, что вам не нужен этот параметр.

0 голосов
/ 26 апреля 2018

Кажется, что входные данные для судоку - это двумерный массив, подобный этому:

let grid = [
  [2,4,1,7,6,8,5,3,9],
  [5,7,3,9,2,4,1,8,6],
  [8,9,6,5,3,1,7,4,2],
  [7,3,4,2,9,5,6,1,8],
  [1,8,9,4,7,6,3,2,5],
  [6,5,2,8,1,3,4,9,7],
  [4,6,5,3,8,2,9,7,1],
  [3,2,7,1,5,9,8,6,4],
  [9,1,8,6,4,7,2,5,3]
]

Чтобы проверить судоку, мы должны проверить все строки, столбцы и вложенные сетки

sub-grids explanation

Объяснение кода:

p = a => eval(a.join("*")) == (1*2*3*4*5*6*7*8*9);

Это эквивалентно

p = function(a) {
  return eval(a.join("*")) == (1*2*3*4*5*6*7*8*9);
}

Так что функция "p" получает массив целых чисел

[2,4,1,7,6,8,5,3,9]

объединяет все целые числа с "*", и в результате мы имеем:

"2*4*1*7*6*8*5*3*9"

, затем оцениваем эту строку и в результате получаем:

362880

Этото же значение, что и 1*2*3*4*5*6*7*8*9

Так что теперь мы можем проверить каждую строку, каждый столбец и каждую подсеть с помощью этой функции.

sudoku = grid => 
  grid.every((r,i) =>
    validRows &&
    validColumns &&
    validSubGrids )

- это то же самое, что:

sudoku = function(grid) {
  grid.every( function(r, i) {
    return 
      validRows &&
      validColumns &&
      validSubGrids
  })
}

Метод every выполняет предоставленную функцию обратного вызова один раз для каждого элемента, присутствующего в массиве, пока не найдет элемент, в котором обратный вызов возвращает ложное значение.В противном случае он возвращает true.

Действительное судоку означает, что обратный вызов нашей every функции возвращает true для всех элементов.

p(r) - проверить каждую строку

p(grid.map(r => r[i])) - проверить каждый столбец

функция map создает новый массив.Например, для i=0 будет получен следующий результат:

[ grid[0][0], grid[0][1], grid[0][2],...]

p(r.map((_,j) => grid[3*(i/3|0)+(j/3|0)][3*(i%3)+(j%3)]) ) ) - проверить каждую подсеть

Эквивалентный код:

p(
  r.map( function(_,j) {
    let row = 3 * Math.floor(i/3) + Math.floor(j/3)
    let column = 3 * (i%3) + (j%3)
    return grid[row][column]
  })
)

Таким образом, какВ результате мы проверили все строки, все столбцы и все вложенные сетки.

0 голосов
/ 25 апреля 2018
sudoku = grid => 
  grid.every((r,i) =>
    p(r) &&
    p(grid.map(r => r[i])) &&
    p(r.map((_,j) => grid[3*(i/3|0)+(j/3|0)][3*(i%3)+(j%3)]) ) )
  1. Для каждого элемента r в сетке оценивается p (r).Если это правда, тогда будет вычислена вторая часть
  2. grid.map(r => r[i]), которая, в свою очередь, будет перебирать все элементы сетки и возвращать массив их i -го элемента.

    Теперь, если p(grid.map(r => r[i])) истинно, будет вычислена последняя часть.

  3. Наконец, r.map((_,j) => grid[3*(i/3|0)+(j/3|0)][3*(i%3)+(j%3)]) ) будет выполнено, но только если предыдущие два условия были выполнены.

    Это также вернет массив элементов сетки, в зависимости от значений i & j.

Так что ключевым моментом здесь является использование &&

A && B вернет B, если A оценивается как истина (а B будет оцениваться только когда A истинно)

...