我在一个小例子上做“实验”,以了解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]
数字数组是正确的,但是根数组搞砸了?
答案 0 :(得分:0)
您的过滤器功能正在改变其运行的数字数组;它应该只返回true或false,具体取决于您是否需要筛选结果中的项目。例如
var roots = numbers.filter(function(n) {
return n > 10;
}).map(Math.sqrt);
在这种情况下,数字永远不会更改,但 roots 包含数字中大于10的所有元素。
答案 1 :(得分:0)
你正在使用filter
,但在回调中,你正在做自己的过滤器...我怀疑是故意的。如果你分解你的代码在会话中做的事情,它基本上是#34;对于数组中的每个元素,遍历整个数组(for循环)并在该循环中再次迭代整个数组(indexOf
)...&#34 ;.此时你可能已经确定出错了。另外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]
请注意,这些方法是可链接的,但绝不会改变原始数组。这为执行数组计算提供了极大的灵活性。
答案 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}} 的对于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的值将保留在数字数组中,并且将删除36。
现在,由于已从阵列中移除了25,36和49,1
已完成其工作,filter
将[1, 4, 9]
传递给map
,[1, 2, 3]
。
它实际上提供了正确答案的反转。
<{1}} 的这是真的奇怪的地方。
for循环将删除number < 10
,跳过1
(因为它现在取代1),删除4
(代替9
),跳过4
,并保留其余部分。这将返回25
的值,这是真实的,并且被解释为保持[4, 25, 36, 49]
。
过滤结果为1
。
for循环将删除4,跳过25,并保留其余部分。这会返回[1]
的值,这是真实的,因此被解释为保留[25, 36, 49]
。
过滤器的结果现在为25
for循环将保留所有值,因为它们都大于10,这意味着返回值为[1, 25]
,这是真实的,这意味着保留了49。
过滤器的结果为[25, 36, 49]
,[1, 25, 49]
映射为Math.sqrt
0_o
永远不要修改数组,因为你正在循环或使用数组函数。