首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >JS,数组矩阵的差异与forEach行为

JS,数组矩阵的差异与forEach行为
EN

Stack Overflow用户
提问于 2018-10-12 10:46:52
回答 3查看 136关注 0票数 4

我正在为我的JS课程做一些培训任务,其中一个任务是必须实现一个函数,该函数接受一个正整数(n),并返回一个矩阵,如下所示(5已通过):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[ [ 1, 0, 0, 0, 0 ],
  [ 0, 1, 0, 0, 0 ],
  [ 0, 0, 1, 0, 0 ],
  [ 0, 0, 0, 1, 0 ],
  [ 0, 0, 0, 0, 1 ] ]

我能够用以下代码实现该函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function getIdentityMatrix(n) {
  const mat = new Array(n).fill([]);
  return mat.map((row, index) => {
    row = new Array(n).fill(0);
    row[index] = 1;
    return row;
  });
}

但是在做的时候我发现了一种我无法解释的奇怪的行为..。如果我稍微修改一下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function getIdentityMatrix(n) {
  const mat = new Array(n).fill(new Array(n).fill(0));
  return mat.map((row, index) => {
    row[index] = 1;
    return row;
  });
}

它返回如下矩阵:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[ [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ] ]

为什么会这样?这就像forEach函数对嵌套在每一行中的所有元素进行迭代一样,它不应该这样做。

谢谢你的建议!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-10-12 10:56:13

这是因为Array是一个引用类型。当你做的时候

new Array(n).fill(new Array(n).fill(0))

首先,内部new Array(n).fill(0)使数组大小n填充0;接下来,外部Array(n).fill创建一个由对该内部数组的n个引用填充的数组。

它不创建n个内部数组,只创建对同一个数组的n个引用。因此,当您更改该内部数组的一个元素时,外部数组中的所有引用都将反映更改,因为它们都指向同一个对象。

票数 3
EN

Stack Overflow用户

发布于 2018-10-12 17:02:01

所涉守则相当于:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let n = 5
let innerArr = new Array(n).fill(0)

function getIdentityMatrix(n) {
  const mat = new Array(n).fill(innerArr);
  return mat.map((row, index) => {
    row[index] = 1;
    return row;
  });
}
console.log(getIdentityMatrix(n))

因为您使用的是fill,所以基本上是用对innerArr (which you can see clearly from the above console output)的引用填充这个mat数组。

然后对每个i row[index] = 1进行,它将更改相同数组相同值(在I索引处)。

现在你的例子..。可以用较短的形式写成:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const getIdentityMatrix = (n) =>
   [...Array(n)].map((row, index) => {
     row = Array(n).fill(0)
     row[index] = 1
     return row
   })

console.log(getIdentityMatrix(3))

显然,maps在新创建的n数组上,然后是spreaded数组上,但是随后用一个全新的数组引用覆盖了每个元素

由于该引用是全新的,所以使用row[index] = 1修改它会在我们从地图上进行return the x时产生预期的行为。

另一种在一行中实现这一目标的方法是通过mapObject.assignObject.values实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const gm = (n) => [...Array(n)].map((x,i) => 
   Object.values(Object.assign(Object.assign({}, Array(n).fill(0)), {[i]:1})))

console.log(gm(3))

票数 0
EN

Stack Overflow用户

发布于 2018-10-12 11:03:27

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// your example is roughly equivalent to this.
const innerArray = new Array(n).fill(0);
const mat = new Array(n).fill(innerArray);

(mat[0] === mat[1] === innerArray) === true;

只有一个嵌套数组,而不是n次数组。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52785440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文