使用示例

时间:2018-04-25 20:19:03

标签: javascript ecmascript-6 sudoku arrow-functions

我无法理解使用箭头函数和.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 :(得分:0)

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. 将评估
  3. grid.map(r => r[i]),然后将遍历所有网格项并返回其 i 元素的数组。

    如果p(grid.map(r => r[i]))为真,那么后半部分将被评估。

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

    这也将返回一系列网格项,具体取决于i&的值。学家

  5.   

    所以这里的关键点是&&

    的用法
    如果A计算结果为真,则

    A && B将返回B(仅当A为真时才会评估B)

答案 1 :(得分:0)

在大多数情况下,箭头功能只是一个功能。两者之间唯一真正的区别是,当使用箭头函数时,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就继续前进。 rgrid的当前值,i是它正在处理的当前索引。

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

实际上只是从i-th获取r值并将其返回。这将用于检查二维阵列的对角线。 (因此它得到grid[0][0]grid[1][1]等等。

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

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

答案 2 :(得分:0)

似乎数独的输入数据是像这样的二维数组:

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

要验证Sudoku,我们必须检查所有行,列和子网格

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])) - 验证每一栏

function 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]
  })
)

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