JavaScript中的过滤和映射
Filter and map in JavaScript
我正在做一个小例子"实验",以了解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
会改变原始数组,这通常是不希望看到的。
下面是一个如何使用filter
和map
的示例
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
结论当你在数组上循环或使用数组函数时,永远不要修改数组。
- 如何在映射数组中添加换行符
- 有可能过滤来自嵌入式YouTube的声音吗
- ng映射方向备选方案
- 无法通过数组映射绑定
- ReactJS映射:如何仅在url变量不为空时呈现html链接
- Python 3.3 itertools映射,长度为5,由正则表达式级别过滤
- 正确过滤/映射/减少
- 在 Angular JS 中通过映射键进行过滤
- 映射、过滤和自己的价值
- 使用数组映射过滤带有if条件的结果
- 如何对堆积条形图进行数据映射和过滤
- 如何在 JavaScript 中映射/减少/过滤 Set
- JavaScript中的过滤和映射
- 在ES6中过滤或映射节点器
- 我如何映射&以无点样式过滤
- 使用Ramda映射和过滤对象
- 在过滤后的数组上应用映射函数
- d3映射与复选框过滤
- javascript中的映射和过滤函数
- 同时进行数组过滤和映射