3

I have an array as such: [[1,3],[2,5],[1,3],[2,5]] and i would like to remove any duplicate sub-arrays. I tried using this code:

 uniqueArray = array.filter(function(item, pos) {
   return array.indexOf(item) == pos;   });

It still returns true for all the cases.

Which function can i use to get the desired result.

Aaqib
  • 9,942
  • 4
  • 21
  • 30
Kostis
  • 119
  • 1
  • 12
  • You may want to review https://stackoverflow.com/questions/9229645/remove-duplicates-from-javascript-array – S. Walker Nov 13 '17 at 00:22
  • Will the arrays always be sorted the same way? Is `[1,3]` a duplicate of `[3,1]`? – RobG Nov 13 '17 at 00:53

3 Answers3

4

Conver the 2D array into 1D array with stringified elements

Then put then into a Set to automatically filter out the repeating elements

Now convert the Set back to an array and map the array by JSON parsing each element to restore back the arrays.

Readable and no nested loops.

const arr = [[1,3],[2,5],[1,3],[2,5]];

const setArray = new Set(arr.map(x => JSON.stringify(x)))

const uniqArray = [...setArray].map(x => JSON.parse(x))

console.log(uniqArray)
Nandu Kalidindi
  • 6,075
  • 1
  • 23
  • 36
  • I think this is the most straight forward for me to be honest. Although other ones work aswell – Kostis Nov 13 '17 at 00:35
3

Not the most efficient method, but the sub-arrays can be used as object keys:

a = [[1,3],[2,5],[1,3],[2,5]]

o = a.reduce((r, v) => (r[v] = v, r), {})

console.log(JSON.stringify( Object.values(o) ))
console.log(JSON.stringify( o ))

Update: seems a bit faster with numeric keys :

let a = [[1,3],[2,5],[1,3],[2,5]], t, b, n = _ => performance.now(), 
v = Object.values, l = t => console.log(JSON.stringify(b), t) 

t = n(); b = v(a.reduce((r, v) => (r[v] = v, r), {}))                   ; l(n() - t)

t = n(); b = v(a.reduce((r, v) => (r[v[0] + 1 / v[1]] = v, r), {}))     ; l(n() - t)

t = n(); b = v(a.reduce((r, v) => (r[v[0] + 1 / v[1]] = v, r), new Map)); l(n() - t)
Slai
  • 22,144
  • 5
  • 45
  • 53
2

You can use Array#filter with an object that will store a hash for each iterated tuple:

var arr = [[1,3],[2,5],[1,3],[2,5]];

var result = arr.filter(function(t) {
  var key = t.join('-');
  return this[key] ? false : (this[key] = true);
}, Object.create(null));

console.log(result);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • So basically the object is created as an argument? – Kostis Nov 13 '17 at 00:17
  • Nope. The Object is created as the `this` passed to the object by [Array#filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter). The current tuple (the sub array) is passed as an argument to the callback. – Ori Drori Nov 13 '17 at 00:23
  • 2
    I think "hash" should be renamed "key" or similar and could just be `key = t.join('-')`. – RobG Nov 13 '17 at 00:47