通过示例了解箭头函数

Understanding Arrow functions with an Example

我无法理解使用箭头函数和 .every() 方法的编码挑战的解决方案,希望更有知识的人可以解释发生了什么。挑战在于检查网格以查看它是否代表真正的数独板。我理解第一部分连接和乘以一个 row/col/square,但无法理解后面的部分...

// 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)]) ) )

感谢您的帮助!

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]) 将被评估,这反过来将遍历所有网格项目和 return 它们的 ith 元素的数组.

    现在如果p(grid.map(r => r[i]))为真则后面的部分将被评估。

  3. 最后 r.map((_,j) => grid[3*(i/3|0)+(j/3|0)][3*(i%3)+(j%3)]) ) 将被执行,但前提是前两个条件为真。

    这也将 return 一个网格数组项,取决于 i 和 j 的值。

So key points here is the usage of &&

A && B 将 return B 如果 A 的计算结果为真(并且仅当 A 为真时才计算 B)

在大多数情况下,箭头函数只是一个函数。两者之间唯一真正的区别是 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();

另一个可能会让你失望的区别是箭头函数,如果它只需要一行,你可以省略大括号 ({}) 它会 return价值。即,

a => 1

等同于:

function (a) { return 1; }

在此示例代码中,作为箭头函数或常规函数没有区别,因为未调用 this

代码的作用是:

grid.every((r, i) =>

查看 grid 中的每个元素,并一直持续到 returns truergrid 的当前值,i 是它正在处理的当前索引。

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

实际上只是从 r 获取 i-th 值并 returning 它。这将用于检查二维数组的对角线。 (所以它得到 grid[0][0]grid[1][1],等等)。

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

然后只是遍历 r 中的每个元素,并使用来自外循环的当前 i 索引和 j 索引获取一些元素(基于该数学)来自 r。使用 _ 作为参数名称是一种常见的约定,表示您不关心该参数。

似乎数独的输入数据是二维数组,如下所示:

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]
]

为了验证数独,我们必须检查所有行、列和子网格

代码解释:

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 方法为数组中存在的每个元素执行一次提供的回调函数,直到找到一个回调函数 returns 为假值。否则 returns 为真。

有效数独意味着我们的 every 函数对所有元素的回调 returns 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]
  })
)

因此,我们验证了所有行、所有列和所有子网格。