2D数组上的Javascript map()

v440hwme  于 2023-05-27  发布在  Java
关注(0)|答案(6)|浏览(148)

我希望newArray[4, 2, 5],但我在2D数组中得到了3个副本。它似乎与console.log所说的不匹配。为什么?

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

let newArray = myArray.map(function(currentArray){
  this.push(currentArray[3]);
  console.log("this: " + this);
  return this;
}, []);

console.log(newArray);
aij0ehis

aij0ehis1#

似乎是一个简单的任务,试图使用this作为map中的结果数组没有意义,this通常是被Map的数组。但在我的例子中,我使用了一个箭头函数来Map,所以它内部的this引用外部作用域的this

const myArray = [
  [1, 2, 3, 4, 5, 6, 7, 8],
  [8, 7, 5, 2, 4, 6, 1, 6],
  [9, 2, 4, 5, 1]
];

const mapIndex = (arr, idx) => arr.map(arr => arr[idx]);

console.log(mapIndex(myArray, 3));
dojqjjoe

dojqjjoe2#

一行解决方案,.map()已经为您创建了一个新数组,因此只需像这样返回每个数组的第4个元素

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

let newArray = myArray.map(x => { return x[3]; });

console.log(newArray);

或者让它变短

let newArray = myArray.map(x => x[3] );
9udxz4iz

9udxz4iz3#

Array.prototype.map()为数组中的每个元素调用一次其提供的callbackFn函数,并根据结果构造一个新数组。
在我们的例子中,我们正在操作的数组有3个元素,所以map将调用回调函数3次。
这里还提供了第二个参数,它将在执行callbackFn时用作this。您传递的值是一个新数组。
让我们用一些变量重写你的示例代码,以便于讨论:

const item1 = [1, 2, 3, 4, 5, 6, 7, 8];
const item2 = [8, 7, 5, 2, 4, 6, 1, 6];
const item3 = [9, 2, 4, 5, 1];

const myArray = [
 item1,
 item2,
 item3,
];

const thisArg = [];

const newArray = myArray.map(function callbackFn(currentArray) {
  this.push(currentArray[3]);
  return this;
}, thisArg);

好,让我们逐步完成callbackFn调用的每个迭代

1)第一次迭代

  • 在开始时,一些值是:
  • currentArrayitem1
  • this是空数组[]
  • map返回的“累加器”也初始化为一个不同的空数组[]

1.所以我们执行这个函数
1.抓取item1[3],即4
1.将其推到this上,该this变为[4]
1.返回this,*,它将 *“添加”到我们的累加器中。所以我们的累加器现在看起来像[[4]]。记住,我们的累加器是一个数组,当我们返回this时,它会将该项添加到它。
到目前为止一切顺利吗好,下一步:

2)第二次迭代

  • 在第二次迭代开始时,一些值为:
  • currentArrayitem2
  • this[4]
  • “累加器”是[thisArg]

1.请注意,累加器只是保存referencethisArg,而不是副本。这很重要!现在让我们执行回调
1.抓取item2[3],即2
1.将其推到this上,该this变为[4, 2]
1.返回this,所以我们的累加器现在是[thisArg, thisArg]。它持有对同一数组的两个引用!由于thisArg看起来像[4, 2],这意味着累加器看起来像[[4, 2], [4, 2]]。记住,这些元素不是两个不同的数组,它们是同一个数组!
第三步现在应该有意义了。

3)第三次迭代

  • 开始时:
  • currentArrayitem3
  • this[4, 2]
  • “累加器”是[thisArg, thisArg]

1.执行:
1.抓取item3[3],即5
1.将其推到this上,即变为[4, 2, 5]
1.返回this,因此我们的累加器现在是[thisArg, thisArg, thisArg],其计算结果为[[4, 2, 5], [4, 2, 5], [4, 2, 5]]
我们结束了!返回累加器,并将newArray设置为该值。
为了进一步证明newArray包含对同一对象的3个引用,可以第四次改变该对象,并观察newArray如何改变。

// After your map call...
newArray[0].push(9);

console.log(JSON.stringify(newArray));
// logs "[ [4, 2, 5, 9], [4, 2, 5, 9], [4, 2, 5, 9] ]"

有关更多信息,请参阅map文档以及迭代方法(如map)如何与可选的thisArg一起工作。

khbbv19g

khbbv19g4#

一个更小的形式是:

myArray.map(a => a[3])

它只从每个子数组中选择索引为3的元素。
无论何时看到像x = [ ]和更高版本的不带条件的x.push(...)这样的模式,通常都可以用x = y.map(...)更好地表示代码

bjp0bcyl

bjp0bcyl5#

因为你在map()函数中使用了this,而没有提供数组作为第二个参数。在本例中,map()默认使用空数组。当引用this时,它实际上指向默认的空数组。在每次迭代中,空数组被每个子数组的第四个元素填充并返回。这将导致生成三个数组,每个数组都包含指定的值,从而导致意外的输出。
这是正确的代码版本

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

let newArray = myArray.map(function(currentArray){
  return currentArray[3];
});

console.log(newArray);
kxeu7u2r

kxeu7u2r6#

你也可以通过使用一个简单的for循环来实现这一点。

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

let flattenedArr = [];
let result = [];

for(let rows = 0; rows < myArray.length; rows++){
    flattenedArr = myArray[rows]
    result.push(flattenedArr[3])
}
    
console.log(result)

相关问题