我正在尝试使用如下的reduce方法来消除重复,但是,它不是很有效:
var unique = function(array) {
array = array.sort(function(a,b) {return a-b;});
var noDup = [array[0]];
array.reduce(function(c,d) {
if(c!==d) {
noDup.push(d);
return d;
}
});
return noDup;
};
var x = [9,2,1,5,9,1,1,4,2,9];//==>[1, 1, 2, 4, 5, 9, 9]
答案 0 :(得分:3)
function unique(values) {
return values.reduce(function(prev, cur) {
if (prev.indexOf(cur) == -1) {
prev.push(cur);
}
return prev;
}, []);
}
unique([9,2,1,5,9,1,1,4,2,9]) // --> [9, 2, 1, 5, 4]
答案 1 :(得分:2)
您正在使用"中间值" reduce
保留前一个值,以便您可以在下次检查时对其进行检查。但是这使你无法计算你想要的真正中间值,这是你正在构建的唯一数组,所以你必须在外面声明它(noDup
),这样会破坏整个目的。然后,您的代码存在诸如未向reduce
提供初始值等问题。在这种情况下,reduce
有一个特殊的行为,即它使用数组的前两个值调用回调;你处理不当的情况。
无论如何,因为你似乎愿意对数组进行排序,所以你可以避免每次循环都做indexOf
,只需记住前一个值并检查它:
function unique(values) {
var prev;
return values . sort() . reduce(function(result, cur) {
if (cur !== prev) result.push(cur);
prev = cur;
return result;
}, []);
}
但实际上我们并不需要保持prev
的价值;相反,我们可以简单地直接引用前一个元素,因为filter
将索引和数组的其他参数传递给回调,所以:
function unique(values) {
return values . sort() . reduce(function(result, cur, index, array) {
if (cur !== array[index-1]) result.push(cur);
return result;
}, []);
}
但是如果你考虑一下,这只不过是使用reduce编写的过滤器。它只是过滤掉与前一个相同的数字。所以只需将其作为过滤器开头:
function unique(values) {
return values . sort() . filter(value, i, arr) { return value !== arr[i-1]; });
}
还有其他方法可以使用不需要排序的过滤器来删除重复项。这是一个简单的问题:
values . filter(function(value, i, arr) { return arr.indexOf(value) === i; });
这就是说,如果在数组中首次找到它的位置是它的位置,则过滤掉一个数字。换句话说,过滤出数组中较早出现的数字。