在JavaScript中过滤和映射

时间:2016-11-12 16:09:13

标签: javascript

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

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]

数字数组是正确的,但是根数组搞砸了

3 个答案:

答案 0 :(得分:0)

您的过滤器功能正在改变其运行的数字数组;它应该只返回true或false,具体取决于您是否需要筛选结果中的项目。例如

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

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

example fiddle

答案 1 :(得分:0)

你正在使用filter,但在回调中,你正在做自己的过滤器...我怀疑是故意的。如果你分解你的代码在会话中做的事情,它基本上是#34;对于数组中的每个元素,遍历整个数组(for循环)并在该循环中再次迭代整个数组(indexOf )...&#34 ;.此时你可能已经确定出错了。另外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]

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

答案 2 :(得分:0)

此代码没有按照您的想法执行。这将是非常奇怪的行为,因为你在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循环将通过并修改数组。

<{1}} 的

filter:值1

对于for循环的前3次迭代,没有任何反应,那么:

number > 10,因此i = 3 = 25.这会在for循环中传递条件,从而导致numbers[3],这会将数字更改为splice

这是奇怪的#1

在for循环的下一次迭代中,[1, 4, 9, 36, 49]将为4,但数组已更改。您可能希望接下来检查36的值,但由于数组已被修改,而36现在在25的位置,它将被遗漏。要检查的下一个值实际上是49.类似的推理表明49也将被删除。

当for循环完成后,您将离开i

然后返回numbers = [1, 4, 9, 36],这是真实的,哪个过滤器解释为在数组中保留numbers的指令。

过滤器:值4和9

可以遵循相同的推理,以显示4和9的值将保留在数字数组中,并且将删除36。

现在,由于已从阵列中移除了25,36和49,1已完成其工作,filter[1, 4, 9]传递给map[1, 2, 3]

结果

它实际上提供了正确答案的反转。

<{1}} 的

这是真的奇怪的地方。

filter:值1

for循环将删除number < 10,跳过1(因为它现在取代1),删除4(代替9),跳过4,并保留其余部分。这将返回25的值,这是真实的,并且被解释为保持[4, 25, 36, 49]

到目前为止,

过滤结果为1

filter:值为25(因为它现在位于数组中的第2个位置,因为1被删除)

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

到目前为止,

过滤器的结果现在为25

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

for循环将保留所有值,因为它们都大于10,这意味着返回值为[1, 25],这是真实的,这意味着保留了49。

过滤器的结果为[25, 36, 49][1, 25, 49]映射为Math.sqrt

结果

0_o

结论

永远不要修改数组,因为你正在循环或使用数组函数。