Using the reduce method to eliminate any duplicated numbers

1.7k views Asked by At

I am trying to use the reduce method as follows to eliminate duplicates however, it is not quite working:

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]
2

There are 2 answers

1
AudioBubble On BEST ANSWER

You are using the "intermediate value" of reduce to hold the previous value, so you can check against it the next time through. But that leaves you with no way to calculate the real intermediate value you want, which is the unique array you are building, so you having to declare it outside (noDup), which sort of defeats the whole purpose. Then your code has issues such as not providing an initial value to reduce. In that case, reduce has a special behavior which is that it calls the callback with the first two values of the array; a situation you are not handling properly.

Anyway, since it seems you are willing to sort the array, you can avoid doing an indexOf each time through the loop, by just remembering the previous value and checking against it:

function unique(values) {
    var prev;
    return values . sort() . reduce(function(result, cur) {
        if (cur !== prev) result.push(cur);
        prev = cur;
        return result;
    }, []);
}

But it turns out actually we don't need to keep the value of prev; instead, we can simply refer to the previous element directly, since filter passes additional arguments of index and array to the callback, so:

function unique(values) {
    return values . sort() . reduce(function(result, cur, index, array) {
        if (cur !== array[index-1]) result.push(cur);
        return result;
    }, []);
}

But if you think about it, this is nothing more than a filter written using reduce. It's just filtering out numbers that are the same as the previous one. So just write it as a filter to start with:

function unique(values) {
    return values . sort() . filter(value, i, arr) { return value !== arr[i-1]; });
}

There are other approaches to removing duplicates using filter which don't require the sort. Here's a simple one:

values . filter(function(value, i, arr) { return arr.indexOf(value) === i; });

What this says is, filter out a number if the location where it is first found in the array is its location. In other words, filter out numbers that occur earlier in the array.

0
Andreas On
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