47

I need to filter out my array to contain only unique values. this is my array data

["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"]

expected result should be

["X_row7", "X_row4", "X_row6", "X_row10", "X_row11", "X_row8", "X_row9"]

How should i continue my code to get proper result.

newArray = [];
for(n in data){
  if(!newArray.indexOf(n)){
     newArray.push(n);
  }
}
console.log(newArray);

If you need any additional information's please let me know and i will provide. thank you

Valor_
  • 3,461
  • 9
  • 60
  • 109
  • 1
    `["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"].filter(function(v,i,arr){ return i==arr.indexOf(v); })` – Pranav C Balan Jul 05 '16 at 15:11
  • Please double-check your expected output - why isn't `X_row9` included? – CertainPerformance Aug 09 '19 at 04:47
  • using loop: var x = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10"]; let itm =[]; for (let i = 0; i < x.length; i++) { let element = x[i]; if(i === x.indexOf(element)) { itm.push(element) } } console.log("item", itm); – Tameshwar Mar 06 '21 at 06:28

11 Answers11

98

You can use Array.filter function to filter out elements of an array based on the return value of a callback function. The callback function runs for every element of the original array.

The logic for the callback function here is that if the indexOf value for current item is same as the index, it means the element has been encountered first time, so it can be considered unique. If not, it means the element has been encountered already, so should be discarded now.

var arr = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"];

var filteredArray = arr.filter(function(item, pos){
  return arr.indexOf(item)== pos; 
});

console.log( filteredArray );

Caveat: As pointed out by rob in the comments, this method should be avoided with very large arrays as it runs in O(N^2).

UPDATE (16 Nov 2017)

If you can rely on ES6 features, then you can use Set object and Spread operator to create a unique array from a given array, as already specified in @Travis Heeter's answer below:

var uniqueArray = [...new Set(array)]
Mohit Bhardwaj
  • 9,650
  • 3
  • 37
  • 64
  • 1
    The original ES5 solution is O(N^2) so make sure your arrays aren't too big if you're using that. – rob Mar 12 '19 at 18:42
40

As of June 15, 2015 you may use Set() to create a unique array:

var uniqueArray = [...new Set(array)]

For your Example:

var data = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"]
var newArray = [...new Set(data)]
console.log(newArray)

>> ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"]
Travis Heeter
  • 13,002
  • 13
  • 87
  • 129
15

Filtering an array to contain unique values can be achieved using the JavaScript Set and Array.from method, as shown below:

Array.from(new Set(arrayOfNonUniqueValues));

Set

The Set object lets you store unique values of any type, whether primitive values or object references.

Return value A new Set object.

Array.from()

The Array.from() method creates a new Array instance from an array-like or iterable object.

Return value A new Array instance.

Example Code:

const array = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"]

const uniqueArray = Array.from(new Set(array));

console.log("uniqueArray: ", uniqueArray);
JSON C11
  • 11,272
  • 7
  • 78
  • 65
7

You could use a hash table for look up and filter all not included values.

var data = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"],
    unique = data.filter(function (a) {
        return !this[a] && (this[a] = true);
    }, Object.create(null));

console.log(unique);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
7

arr = ["I", "do", "love", "JavaScript", "and", "I", "also", "do", "love", "Java"];

uniqueArr = [... new Set(arr)];

// or

reallyUniqueArr = arr.filter((item, pos, ar) => ar.indexOf(item) === pos)

console.log(`${uniqueArr}\n${reallyUniqueArr}`)
Jesse Dirisu
  • 101
  • 1
  • 2
7
Array.prototype.unique = function () {
  return [...new Set(this)]
}

then we can write:

const arr = [1, 5, 2, 2, 2, 3, 4, 3, 2, 1, 5]
const uniqueArr = arr.unique()
Zuhair Taha
  • 2,808
  • 2
  • 35
  • 33
  • Nice concise solution, it works great! When I try as `Array.prototype.unique = () => [...new Set(this)];`, I get `"Uncaught (in promise) TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))"`. Any ideas? Thanks! – AjCodez May 30 '20 at 21:54
  • 2
    Because `this` refer to `window` when you use arrow function, but refer to the array when you use normal function. – Zuhair Taha Oct 12 '20 at 13:28
5

You can use Map and Spread Operator:

var rawData = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"];

var unique = new Map();
rawData.forEach(d => unique.set(d, d));
var uniqueItems = [...unique.keys()];

console.log(uniqueItems);
Morteza Tourani
  • 3,506
  • 5
  • 41
  • 48
4

You can use reduce to loop the array and get the not duplicate values. Also uses an aux object to get the count of added values.

var aux = {};

var newArray = ["X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11", "X_row7", "X_row4", "X_row6", "X_row10", "X_row8", "X_row9", "X_row11"].reduce((tot, curr)=>{
  if(!aux[curr]){
    aux[curr] = 1;
    tot.push(curr);
  }
  return tot;
}, []);

console.log(newArray);
Jose Hermosilla Rodrigo
  • 3,513
  • 6
  • 22
  • 38
4

This is for es2015 and above as far as I know. There are 'cleaner' options with ES6 but this a great way to do it (with TypeScript).

let values: any[] = [];
const distinct = (value: any, index: any, self: any) => {
    return self.indexOf(value) === index;
};
values = values.filter(distinct);
SovietFrontier
  • 2,047
  • 1
  • 15
  • 33
3

A slight variation on the indexOf method, if you need to filter multiple arrays:

function unique(item, index, array) {
    return array.indexOf(item) == index;
}

Use as such:

arr.filter(unique);
omikes
  • 8,064
  • 8
  • 37
  • 50
2

I've always used:

unique = (arr) => arr.filter((item, i, s) => s.lastIndexOf(item) == i);

But recently I had to get unique values for:

["1", 1, "2", 2, "3", 3]

And my old standby didn't cut it, so I came up with this:

uunique = (arr) => Object.keys(Object.assign({}, ...arr.map(a=>({[a]:true}))));
TennisVisuals
  • 427
  • 5
  • 8