将2D数组嵌套在3D数组中时的奇怪行为

时间:2017-06-02 09:46:51

标签: javascript debugging multidimensional-array

目前我正在开发一个用于javascript中四行的Minimax算法。我决定在数组中存储可能的移动,继续在每个分支的数组中嵌套数组。

但是,当我尝试编辑数组中的某个值时,它会编辑同一列中的所有其他值。

代码:

var BOARD = [
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
    ];

// Put 3 x 2D Arrays into one 3D Array
var NODE_TREE = [BOARD, BOARD, BOARD];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);

Chrome V8解释器输出:

[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ] ]

应该发生什么,但不要:

[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]

Javascript似乎忽略了第一个维度索引号。只有当我使用嵌套在数组中的现有数组时才会发生此问题。如果我要从头开始制作3D数组,那么这个错误就不会发生。

2 个答案:

答案 0 :(得分:1)

当您将BOARD 3次放入数组时,您不会"复制"对于新数组的项目,实际上只是创建了对原始BOARD数组的3个引用。

因此,对这些引用中的任何一个进行的任何更改都将反映在BOARD的所有实例中。

如果要在3d阵列中创建3个不同的阵列,则需要克隆或复制阵列。您可以通过映射外部数组并使用Array.prototype.slice()复制内容来完成此操作;



var BOARD = [
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
    ];
    
// function to map and copy arrays with .slice()
function sliceArrays (outerArray){
  return outerArray.map((arr)=>{
    return arr.slice()
  });
}

var NODE_TREE = [sliceArrays(BOARD), sliceArrays(BOARD), sliceArrays(BOARD)];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);

//[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
//  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
//  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]




答案 1 :(得分:1)

对于懒惰的初始化,您可以使用已解析的JSON字符串。

这会生成一个独立的对象,而不会引用原始对象。



var BOARD = [
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]
    ],
    JSON_BOARD = JSON.stringify(BOARD),
    NODE_TREE = [JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD)];

NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);

.as-console-wrapper { max-height: 100% !important; top: 0; }