为何JS代码中filter会移除所有最小元素?原需求仅移除一个
问题:移除数组第一个最小元素时的逻辑错误分析
我需要从数组中仅移除第一个出现的最小元素(即使存在多个相同的最小值),但下面的代码却移除了所有最小元素。我有个疑问:minNum明明是第一个最小元素1的索引2,为什么filter会把第二个1也移除?
原问题代码
const arr = [6, 3, 1, 4, 1]; const removeSmallestNum = function(arr) { const copy = arr.slice(); const minNum = copy.indexOf(Math.min(...copy)); console.log(minNum); return copy.filter(num => copy.indexOf(num) !== minNum); } const result = removeSmallestNum(arr); console.log(result)
代码执行逻辑拆解
我们一步步拆解这段代码的运行过程:
const copy = arr.slice();复制原数组,此时copy的值为[6, 3, 1, 4, 1]。Math.min(...copy)计算出数组最小值是1,接着copy.indexOf(1)找到第一个1的索引2,所以minNum = 2。- 关键问题出在
filter的回调函数:num => copy.indexOf(num) !== minNum- 遍历数组每个元素时,
copy.indexOf(num)始终返回第一个匹配元素的索引:- 遍历到第一个
1时,copy.indexOf(1)是2,等于minNum,所以被过滤掉; - 遍历到第二个
1时,copy.indexOf(1)还是2(因为indexOf只找第一个出现的1),同样等于minNum,所以也被过滤掉; - 其他元素的
indexOf结果都不等于2,因此被保留。
- 遍历到第一个
- 最终两个
1都被移除,得到结果[6, 3, 4],不符合需求。
- 遍历数组每个元素时,
正确实现方式(使用splice)
CodeWars上的正确写法是用splice替代filter,splice可以精准删除指定索引的单个元素:
const removeSmallestNum = function(arr) { const copy = arr.slice(); const minIndex = copy.indexOf(Math.min(...copy)); copy.splice(minIndex, 1); // 从索引minIndex的位置删除1个元素 return copy; }
注意:如果直接return copy.splice(minIndex, 1),返回的是被删除的元素(即[1]),而不是修改后的数组。需要先执行splice修改数组,再返回copy才能得到移除第一个最小元素后的数组。
内容的提问来源于stack exchange,提问作者Olorin
相关产品推荐
相关产品推荐

