111

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

Pavel Zubkou
  • 825
  • 9
  • 13
NaveenDAlmeida
  • 1,251
  • 2
  • 10
  • 11

17 Answers17

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;
    }, []);
};
Pedro L.
  • 7,376
  • 3
  • 25
  • 27
  • 31
    Nonsense! You DO need to use semicolons! http://jsfiddle.net/bTNc2/ – jack Nov 15 '13 at 14:52
  • 2
    Douglas Crockford would be having fits @countfloortiles. You need semicolons. – Simon Nov 28 '13 at 03:04
  • 107
    It's 2014 now, so we need semicolons again. – tacone Jan 08 '14 at 17:35
  • 4
    @PedroL. "You need semicolons if you want to minify your code?" Why do you say that? Omitting semicolons is a way of minifying your code. A semicolon character takes just as much space as a newline character. Replacing all your newlines with semicolons will not give you smaller code. But the process of "minifying" it will become yet another point of potential failure, and your end result will be obfuscated code that is difficult to debug. – Val Kornea May 30 '14 at 10:05
  • 2
    @PedroL. Just want to mention that this function is case-sensitive, so you still could have duplicates. `c = c.toString().toLowerCase();` solved this for me. – Alex2php Sep 11 '14 at 07:49
  • 1
    using `p.indexOf(c) == -1` is better? and I vote for this cool solution! – Huei Tan Oct 23 '14 at 02:31
  • If you understand how semicolons work in Javascript, using them is a matter of style. If you don't, they'll confuse you no matter what you do. Here's a good write-up: http://inimino.org/~inimino/blog/javascript_semicolons To minify Javascript correctly, you need a full parser anyway, so it shouldn't be a problem. – Owen Nov 03 '14 at 16:15
  • 56
    It's 2015 now, so we don't need semicolons again. – Mark Knol Feb 24 '15 at 22:05
  • 11
    This is where you are wrong @MarkKnol. It is now April, and everyone knows that semicolons are required in the Spring and Summer of the Northern Hemisphere. Granted your comment was written in Feb, so I suppose you should be granted some leeway. By the way, can someone come back in Autumn (Fall for y'all) and remove the semi-colons? – dewd Apr 24 '15 at 09:10
  • 1
    Can this function be a prototype? – jscripter Jul 09 '15 at 03:50
  • 49
    Will we need to use semicolons in 2016? – Dumbo Sep 13 '15 at 14:38
  • 11
    It's an even year, so yes, you do need semicolons :) – Foo L Jan 07 '16 at 00:44
  • 1
    this has O(n^2) performance and is therefore undesirable for large arrays. the same work can be done in O(n) time as shown by some of the other solutions below, which use hashing. – akarve Mar 08 '16 at 19:30
  • The solution above is O(n).... `indexOf` doesn't look up the array. It knows exactly where the value is stored it's a O(1) operation. – radical_edo Apr 15 '16 at 20:25
  • 28
    It is midway through 2016 now, and for the most part it's been a `semicolons are optional but highly encouraged` year. – trex005 Jun 07 '16 at 21:47
  • 1
    With good minifiers, you don't need semicolons, as they will take care of that for you. We code in ES6 ([babel](https://babeljs.io/)) and use (almost) no semicolons and our production environment is fully minified. – zpr Jul 06 '16 at 04:33
  • 9
    It's 2016 now, we need semicolons again – jssridhar Oct 21 '16 at 18:16
  • 5
    It's 2042 here, what are semicolons ? – Adel 'Sean' Helal Jun 18 '17 at 02:10
  • 1
    So. It's 2017 now. Year of the Fire Rooster Ding You. Semicolons or not? – Mangled Deutz Jul 02 '17 at 07:38
  • 3
    @MangledDeutz Full colons now. – Brilliand Jul 21 '17 at 04:21
  • 2
    @MangledDeutz in 2017 [this happened](https://bugs.webkit.org/show_bug.cgi?id=176114). – James Donnelly Sep 15 '17 at 11:13
  • 3
    It's now 2017, and according to [**StandardJS**](https://standardjs.com/#the-rules), we should **not** use semicolons. They cite [**these**](http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding) [**three**](http://inimino.org/~inimino/blog/javascript_semicolons) [**references**](https://www.youtube.com/watch?v=gsfbh17Ax9I) for their reasoning. – Obsidian Age Sep 17 '17 at 07:43
  • 7
    It's now 2018. We have decided no matter which semicolon standard you use, whoever takes over your project will explain convincingly that the previous dev was an idiot for choosing that standard. – trex005 Jan 03 '18 at 10:30
  • It's 2018 and now TC39 recommends using semicolons to avoid hazards of ASI - https://github.com/tc39/ecma262/pull/1062 – tabrindle Jan 27 '18 at 22:57
  • It's the year 3000, use mixed semicolons, either alternate or use semicolons on even lines. If you add new lines to your code you will need to refactor all lines so that they continue to follow the first rule. – CTS_AE Apr 05 '18 at 19:21
  • 1
    @jack I bow to you for sparking a brilliant comment thread on this post! – dewd Apr 30 '18 at 18:58
  • It's now 2018. I give up JavaScript. – Cai Yongji May 25 '18 at 04:02
  • 2019; still a mixed bag, developers [continue to use spaces instead of tabs for indentation without regard for global warming](https://peterbraden.co.uk/article/space-infidel/). – amcgregor Jan 08 '19 at 18:34
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'].

Cœur
  • 37,241
  • 25
  • 195
  • 267
beatgammit
  • 19,817
  • 19
  • 86
  • 129
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;
};
Jonik
  • 80,077
  • 70
  • 264
  • 372
mahesh
  • 332
  • 4
  • 7
14

With underscorejs

_.uniq([1, 2, 1, 3, 1, 4]); //=> [1, 2, 3, 4]
fguillen
  • 36,125
  • 23
  • 149
  • 210
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

OhJeez
  • 2,774
  • 2
  • 14
  • 18
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.

Jake Rowsell
  • 466
  • 5
  • 16
Raekye
  • 5,081
  • 8
  • 49
  • 74
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);
pepyakin
  • 2,217
  • 19
  • 31
Julius Loa
  • 173
  • 1
  • 7
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);
CMCDragonkai
  • 6,222
  • 12
  • 56
  • 98
  • 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. – terrinecold Sep 09 '14 at 13:28
  • and here is a better performance study: http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/ – terrinecold Sep 09 '14 at 13:34
  • @terrinecold terrific, you should post up an answer referencing that. Would be great if the javascript compiler/interpreter automatically optimised it. – CMCDragonkai Sep 11 '14 at 05:26
  • @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. – CMCDragonkai Sep 11 '14 at 05:32
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;     
}
Musa
  • 96,336
  • 17
  • 118
  • 137
NaveenDAlmeida
  • 1,251
  • 2
  • 10
  • 11
  • 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) – Raekye Nov 21 '12 at 04:56
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;
}
Darshan
  • 750
  • 7
  • 19
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;
}
Amiga500Kid
  • 418
  • 3
  • 8
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));
        }
    );
}
DrunkenBeetle
  • 267
  • 4
  • 2
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;
    }
}
Mitul Maheshwari
  • 2,647
  • 4
  • 24
  • 38
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"]

  • Of course, this would only work for strings. – Bergi Feb 24 '15 at 22:09
  • …and the result should not contain the property names of the initial array, but the actual items. Expected: `['0', '1', '2', '3']` – Bergi Feb 24 '15 at 22:11
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.

akond
  • 15,865
  • 4
  • 35
  • 55
-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;
      }
    );
    //
public override
  • 974
  • 8
  • 17
-4
Array.prototype.unique =function(){
    var uniqObj={};
    for(var i=0;i< this.length;i++){
      uniqObj[this[i]]=this[i]; 
    }
    return uniqObj;
}
  • 4
    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. – bitoiu Mar 27 '14 at 11:05