JavaScript中的过滤和映射

Filter and map in JavaScript

本文关键字:映射 过滤 JavaScript      更新时间:2023-09-26

我正在做一个小例子"实验",以了解filter()map()在JavaScript中的使用,我有一个问题,基于以下代码。

var numbers = [1, 4, 9, 25, 36, 49];
var roots = numbers.filter(function() {
  for (i = 0; i < numbers.length; i++) {
        if (numbers[i] > 10) {
        var index = numbers.indexOf(numbers[i]);
      numbers.splice(index, 1);
    }
  }
  return numbers;
}).map(Math.sqrt);
console.log(numbers);
// -> [1, 4, 9]
console.log(roots);
// -> [1, 2, 3]

为什么当我把numbers[i] > 10作为条件时输出是正确的,而如果我把numbers[i] < 10作为条件,结果是以下

console.log(numbers);
// -> [25, 36, 49]
console.log(roots);
// -> [1, 5, 7]

其中数字数组是正确的,但根数组是混乱?

您的过滤器函数正在改变其操作的数字数组;它应该只返回true或false,具体取决于您是否希望在过滤后的结果中包含该项。例如

var roots = numbers.filter(function(n) {
        return n > 10;
  }).map(Math.sqrt);

在这种情况下,numbers永远不会改变,但是roots包含数字中大于10的所有元素。

例子小提琴

您正在使用filter,但在回调中,您正在做自己的过滤器…我怀疑这是故意的如果你分解你的代码在对话中做什么,它基本上是"对于数组中的每个元素,遍历整个数组(for循环),并在该循环中再次遍历整个数组(indexOf)……"。在这一点上,您可能可以确定出了问题。此外,Array.splice会改变原始数组,这通常是不希望看到的。

下面是一个如何使用filtermap的示例

var numbers = [1, 4, 9, 25, 36, 49];
// get numbers greater than 10
numbers.filter(n => n > 10)
// => [25, 36, 49]
// get numbers greater than 10 and take the square root of each number
numbers.filter(n => n > 10).map(Math.sqrt)
// => [5, 6, 7]

请注意,这些方法是可链接的,但不会改变原始数组。这为执行数组计算提供了很大的灵活性。

这段代码并没有做你认为它在做的事情。它会表现得很奇怪因为你在for循环中改变了数字数组

filter的正确用法是为每个值返回true/false,而不是返回一个新的数组。返回true保留一个元素,返回false删除该元素。

这就是你要找的:

var numbers = [1, 4, 9, 25, 36, 49];
// notice "number" is taken as an argument
var roots = numbers.filter(function(number) {
  // return true to include this number, false to reject it
  return number < 10;
}).map(Math.sqrt);
console.log(numbers);
// NOTE: has not been changed
// -> [1, 4, 9, 25, 36, 49]
console.log(roots);
// -> [1, 2, 3]

为了理解结果从何而来,让我们遍历一下代码的每次迭代:

过滤器将对数组的每个元素运行。然后for循环遍历并修改数组。

for number > 10

filter: value = 1

for循环的前3次迭代,什么都没有发生,然后:

i = 3,所以numbers[3] = 25。这将在for循环中传递条件,导致splice,它将数字更改为[1, 4, 9, 36, 49]

这就是奇怪的地方#1

在for循环的下一次迭代中,i将是4,但是数组已经改变。您可能希望接下来检查36的值,但由于数组已被修改,36现在取代了25,因此将会遗漏36的值。下一个要检查的值实际上是49。类似的推理表明,49也将被删除。

for循环完成后,剩下numbers = [1, 4, 9, 36]

然后返回numbers,这是真值,过滤器将其解释为将1保留在数组中的指令。

过滤器:值4和9

可以遵循同样的推理来显示4和9的值将留在数字数组中,而36将被删除。

现在,因为25,36和49已经从数组中删除,filter已经完成了它的工作,留下[1, 4, 9]传递给map,得到[1, 2, 3]

结果

它实际上提供了正确答案的倒数。

for number < 10

这就是变得奇怪的地方。

filter: value = 1

for循环将删除1,跳过4(因为它现在取代了1),删除9(取代了4),跳过25,并保留其余部分。这将返回值[4, 25, 36, 49],该值为真值,并将其解释为保留1

目前过滤器的结果是[1] .

过滤器:值为25(因为它现在在数组的第二个位置作为1被删除)

for循环将删除4,跳过25,并保留其余部分。这将返回值[25, 36, 49],这是真值,因此解释为保留25

到目前为止过滤器的结果是[1, 25]

过滤器:值为49(因为它现在在数组中的第3个位置,因为1、4和9已经被删除)

for循环将保留所有的值,因为它们都大于10,这意味着返回值将是[25, 36, 49],这是正确的,这意味着49被保留。

过滤器的结果将是[1, 25, 49],与Math.sqrt映射为[1, 5, 7]

结果

0 _o

结论

当你在数组上循环或使用数组函数时,永远不要修改数组。