102

For example, I have an array like this;

var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10]

My purpose is to discard repeating elements from array and get final array like this;

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

How can this be achieved in JavaScript?

NOTE: array is not sorted, values can be arbitrary order.

7
  • You could loop over the array and copy all elements to a map. Commented May 25, 2013 at 8:30
  • @Devolus that's only valid for strings and numbers, you cannot use object or array as index key. Commented May 25, 2013 at 8:31
  • 1
    It's a solution but, is also brute force solution. Is there smarter (efficient) way of this? Commented May 25, 2013 at 8:31
  • 1
    Sort the array, iterate, push element to new array if not the same as last. Commented May 25, 2013 at 8:34
  • 1
    @Devolus: But JavaScript is not like Java. Commented May 25, 2013 at 8:49

5 Answers 5

270

It's easier using Array.filter:

var unique = arr.filter(function(elem, index, self) {
    return index === self.indexOf(elem);
})
Sign up to request clarification or add additional context in comments.

11 Comments

how is this efficient ? Care to explain worst case run time depends on how indexOf works if it runs in linear time, then the worst case time is O(n^2)
@AbKDs please elaborate more on this
@MehmetInce it is not "efficient" at all, that runs in O(n^2)
.filter() iterates over all the elements of the array and returns only those for which the callback returns true. .indexOf() returns the index of the leftmost element in the array. If there are duplicate elements, then for sure they're gonna be removed when their index is compared to the leftmost one. For more info check developer.mozilla.org/it/docs/Web/JavaScript/Reference/… :) @MadPhysicist
This answer is still fine for very small lists though. It has the advantage of being very simple code, so less likely to have bugs in and less effort to read than code using using an auxillary store. It's less flexible though: it wouldn't work if you wanted to eliminate duplicates based on only a single field of items in the list, whereas the other solution would be easy to adapt to that.
|
24

As elements are yet ordered, you don't have to build a map, there's a fast solution :

var newarr = [arr[0]];
for (var i=1; i<arr.length; i++) {
   if (arr[i]!=arr[i-1]) newarr.push(arr[i]);
}

If your array weren't sorted, you would use a map :

var newarr = (function(arr){
  var m = {}, newarr = []
  for (var i=0; i<arr.length; i++) {
    var v = arr[i];
    if (!m[v]) {
      newarr.push(v);
      m[v]=true;
    }
  }
  return newarr;
})(arr);

Note that this is, by far, much faster than the accepted answer.

5 Comments

array is not always sorted.
Its easier than that Making your approach a bit simpler var m = []; arr.forEach( v => m[v]=true ); var newarr = Object.keys(m); Easy, right?
This is a great answer. I would use an ES6 Set rather than an object though, so that the items in the list don't have to be strings. (Obviously that wasn't an option back when the answer was written.)
It's extremely fast with unordered arrays too. Thanks!
Awesome answer! ;)
11
var arr = [1,2,2,3,4,5,5,5,6,7,7,8,9,10,10];

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

console.log(squash(arr));

Working Example http://jsfiddle.net/7Utn7/

Compatibility for indexOf on old browsers

Comments

6

you may try like this using jquery

 var arr = [1,2,2,3,4,5,5,5,6,7,7,8,9,10,10];
    var uniqueVals = [];
    $.each(arr, function(i, el){
        if($.inArray(el, uniqueVals) === -1) uniqueVals.push(el);
    });

Comments

5

Try following from Removing duplicates from an Array(simple):

Array.prototype.removeDuplicates = function (){
  var temp=new Array();
  this.sort();
  for(i=0;i<this.length;i++){
    if(this[i]==this[i+1]) {continue}
    temp[temp.length]=this[i];
  }
  return temp;
} 

Edit:

This code doesn't need sort:

Array.prototype.removeDuplicates = function (){
  var temp=new Array();
  label:for(i=0;i<this.length;i++){
        for(var j=0; j<temp.length;j++ ){//check duplicates
            if(temp[j]==this[i])//skip if already present 
               continue label;      
        }
        temp[temp.length] = this[i];
  }
  return temp;
 } 

(But not a tested code!)

7 Comments

This function doesn't just remove duplicates, it also sorts. Why encumber Array's prototype with such a specific function (which wouldn't work for any type of array as most can't be directly sorted) ?
Maybe better to test for inequality and dispose the continue
@Matanya I am improving my answer
@thg435 I had simple error of { in first code that's why it was not working, now corrected and tested.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.