111

Given a ['0','1','1','2','3','3','3'] array, the result should be ['0','1','2','3'].

4
  • 6
    Yeah dude jquery solves all problems. Commented Jan 20, 2014 at 20:49
  • 1
    You can use a utility library like underscore.js underscorejs.org/#uniq for these "easy" operations Commented Feb 3, 2014 at 9:51
  • 36
    Oh, the irony of a duplicate question. Commented Jul 11, 2015 at 21:17
  • @LucioPaiva where's the array of duplicate questions??? 🤣🤣🤣 Commented Apr 30, 2018 at 18:54

17 Answers 17

257

Edited

ES6 solution:

[...new Set(a)];

Alternative:

Array.from(new Set(a));

Old response. O(n^2) (do not use it with large arrays!)

var arrayUnique = function(a) {
    return a.reduce(function(p, c) {
        if (p.indexOf(c) < 0) p.push(c);
        return p;
    }, []);
};
Sign up to request clarification or add additional context in comments.

28 Comments

Nonsense! You DO need to use semicolons! jsfiddle.net/bTNc2
It's 2014 now, so we need semicolons again.
It's 2015 now, so we don't need semicolons again.
Will we need to use semicolons in 2016?
It is midway through 2016 now, and for the most part it's been a semicolons are optional but highly encouraged year.
|
52

If you want to maintain order:

arr = arr.reverse().filter(function (e, i, arr) {
    return arr.indexOf(e, i+1) === -1;
}).reverse();

Since there's no built-in reverse indexof, I reverse the array, filter out duplicates, then re-reverse it.

The filter function looks for any occurence of the element after the current index (before in the original array). If one is found, it throws out this element.

Edit:

Alternatively, you could use lastindexOf (if you don't care about order):

arr = arr.filter(function (e, i, arr) {
    return arr.lastIndexOf(e) === i;
});

This will keep unique elements, but only the last occurrence. This means that ['0', '1', '0'] becomes ['1', '0'], not ['0', '1'].

10 Comments

Interesting solution, does lastIndexOf work?
Kind of, but it depends on what you mean by that. You could use it if you didn't need order instead of the reverse() hack.
+1 for golfing. Unfortunately the straight for loop seems to perform better JSPerf. Damn function calls are so expensive.
@merv - The OP said nothing about performance, so I got creative. Code's simple enough, no?
Nice! I like [1,2,3,1,1].filter(function(elem,idx,arr){ return arr.indexOf(elem) >= idx; }); better though, it's more straightforward
|
26

Here is an Array Prototype function:

Array.prototype.unique = function() {
    var unique = [];
    for (var i = 0; i < this.length; i++) {
        if (unique.indexOf(this[i]) == -1) {
            unique.push(this[i]);
        }
    }
    return unique;
};

1 Comment

This is the easiest reading code XD
14

With underscorejs

_.uniq([1, 2, 1, 3, 1, 4]); //=> [1, 2, 3, 4]

1 Comment

Would this work for array of arrays
13

It's 2014 now guys, and time complexity still matters!

array.filter(function() {
  var seen = {};
  return function(element, index, array) {
    return !(element in seen) && (seen[element] = 1);
  };
}());

http://jsperf.com/array-filter-unique/13

Comments

9
function array_unique(arr) {
    var result = [];
    for (var i = 0; i < arr.length; i++) {
        if (result.indexOf(arr[i]) == -1) {
            result.push(arr[i]);
        }
    }
    return result;
}

Not a built in function. If the product list does not contain the item, add it to unique list and return unique list.

3 Comments

Might want to mention that this won't work in IE8 or below..
Why would it not work in IE8?
Perhaps because there's a closing parenthesis missing, it should be: result.push(arr[i]);
6

There you go! You are welcome!

Array.prototype.unique = function()
{
    var tmp = {}, out = [];
    for(var i = 0, n = this.length; i < n; ++i)
    {
        if(!tmp[this[i]]) { tmp[this[i]] = true; out.push(this[i]); }
    }
    return out;
}

var a = [1,2,2,7,4,1,'a',0,6,9,'a'];
var b = a.unique();
alert(a);
alert(b);

Comments

3

You can find all kinds of array unique implementations here:

http://jsperf.com/distinct-hash-vs-comparison/12

http://jsperf.com/array-unique-functional

I prefer functional styles such as:

var arr = ['lol', 1, 'fdgdfg', 'lol', 'dfgfg', 'car', 1, 'car', 'a', 'blah', 'b', 'c', 'd', '0', '1', '1', '2', '3', '3', '3', 'crazy', 'moot', 'car', 'lol', 1, 'fdgdfg', 'lol', 'dfgfg', 'car', 1, 'car', 'a', 'blah', 'b', 'c', 'd', '0', '1', '1', '2', '3', '3', '3', 'crazy', 'moot', 'car', 'lol', 1, 'fdgdfg'];

var newarr = arr.reduce(function (prev, cur) {
    //console.log(prev, cur);
    if (prev.indexOf(cur) < 0) prev.push(cur);
    return prev;
}, []);

var secarr = arr.filter(function(element, index, array){
    //console.log(element, array.indexOf(element), index);
    return array.indexOf(element) >= index;
});

//reverses the order
var thirdarr = arr.filter(function (e, i, arr) {
    //console.log(e, arr.lastIndexOf(e), i);
    return arr.lastIndexOf(e) === i;
});

console.log(newarr);
console.log(secarr);
console.log(thirdarr);

4 Comments

I think most of the solutions proposed have a potential problem in that they are computation intensive. They will need O(n^2) operation at least (due to calling indexOf for each iteration). So when using a small array it is nice but not for large arrays. I am making this comment here as there is a link to a performance test and I think it is misleading due to data which is too small.
and here is a better performance study: shamasis.net/2009/09/…
@terrinecold terrific, you should post up an answer referencing that. Would be great if the javascript compiler/interpreter automatically optimised it.
@terrinecold wait, the method posted in your link is the same one in the comparisons that I linked to, and it isn't always faster. I suppose it might be for larger arrays.
1
function array_unique(nav_array) {
    nav_array = nav_array.sort(function (a, b) { return a*1 - b*1; });      
    var ret = [nav_array[0]];       
    // Start loop at 1 as element 0 can never be a duplicate
    for (var i = 1; i < nav_array.length; i++) { 
        if (nav_array[i-1] !== nav_array[i]) {              
            ret.push(nav_array[i]);             
        }       
    }
    return ret;     
}

1 Comment

Not a good implementation for something called array_unique because you rely on it being an numeric value. Even for a number-array-unique, I think parseInt would be better way to go (I could be wrong)
1

This will work. Try it.

function getUnique(a) {
  var b = [a[0]], i, j, tmp;
  for (i = 1; i < a.length; i++) {
    tmp = 1;
    for (j = 0; j < b.length; j++) {
      if (a[i] == b[j]) {
        tmp = 0;
        break;
      }
    }
    if (tmp) {
      b.push(a[i]);
    }
  }
  return b;
}

Comments

1

I like to use this. There is nothing wrong with using the for loop, I just like using the build-in functions. You could even pass in a boolean argument for typecast or non typecast matching, which in that case you would use a for loop (the filter() method/function does typecast matching (===))

Array.prototype.unique =
function()
{
    return this.filter(
        function(val, i, arr)
        {
            return (i <= arr.indexOf(val));
        }
    );
}

Comments

1

No redundant "return" array, no ECMA5 (I'm pretty sure!) and simple to read.

function removeDuplicates(target_array) {
    target_array.sort();
    var i = 0;

    while(i < target_array.length) {
        if(target_array[i] === target_array[i+1]) {
            target_array.splice(i+1,1);
        }
        else {
            i += 1;
        }
    }
    return target_array;
}

Comments

1

Here is the way you can do remove duplicate values from the Array.

function ArrNoDupe(dupArray) {
   var temp = {};
    for (var i = 0; i < dupArray.length; i++) {
         temp[dupArray[i]] = true;
         var uniqueArray = [];
       for (var k in temp)
           uniqueArray.push(k);
 return uniqueArray;
    }
}

Comments

1

Another approach is to use an object for initial storage of the array information. Then convert back. For example:

var arr = ['0','1','1','2','3','3','3'];
var obj = {};

for(var i in arr) 
    obj[i] = true;

arr = [];
for(var i in obj) 
    arr.push(i);

Variable "arr" now contains ["0", "1", "2", "3", "4", "5", "6"]

2 Comments

Of course, this would only work for strings.
…and the result should not contain the property names of the initial array, but the actual items. Expected: ['0', '1', '2', '3']
0

Those of you who work with google closure library, have at their disposal goog.array.removeDuplicates, which is the same as unique. It changes the array itself, though.

Comments

-2
    //
    Array.prototype.unique =
    ( function ( _where ) {
      return function () {
        for (
          var
          i1 = 0,
          dups;
          i1 < this.length;
          i1++
        ) {
          if ( ( dups = _where( this, this[i1] ) ).length > 1 ) {
            for (
              var
              i2 = dups.length;
              --i2;
              this.splice( dups[i2], 1 )
            );
          }
        }
        return this;
      }
    } )(
      function ( arr, elem ) {
        var locs  = [];
        var tmpi  = arr.indexOf( elem, 0 );
        while (
          ( tmpi ^ -1 )
          && (
            locs.push( tmpi ),
            tmpi = arr.indexOf( elem, tmpi + 1 ), 1
          )
        );
        return locs;
      }
    );
    //

Comments

-4
Array.prototype.unique =function(){
    var uniqObj={};
    for(var i=0;i< this.length;i++){
      uniqObj[this[i]]=this[i]; 
    }
    return uniqObj;
}

1 Comment

If you tested this out, or even gave an example of a test, you would have seen that this returns an object and not the desired output the user asked for. Please test your code next time.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.