使用 reduce 方法消除任何重复的数字

Using the reduce method to eliminate any duplicated numbers

我正在尝试使用如下的 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]
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]

fiddle

您正在使用 reduce 的 "intermediate value" 来保存以前的值,因此您可以在下次检查时对照它。但这使您无法计算所需的实际中间值,即您正在构建的唯一数组,因此您必须在外部声明它 (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写的filter。它只是过滤掉与前一个相同的数字。所以就把它写成一个过滤器开始:

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; });

这里说的是,过滤掉一个数字,如果它在数组中第一个找到的位置就是它的位置。换句话说,过滤掉数组中较早出现的数字。