Skip to content Skip to sidebar Skip to footer

Map/set To Maintain Unique Array Of Arrays, Javascript

I am trying to build unique array of arrays such that whenever I have new array to add it should only add if it doesn't already exist in collection E.g. store all unique permutatio

Solution 1:

One way would be to convert the arrays to JSON strings, then use a Set to get unique values, and convert back again

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

let set  = newSet(arr.map(JSON.stringify));
let arr2 = Array.from(set).map(JSON.parse);

console.log(arr2)

Solution 2:

To get around the problem of each array being a unique object, you can stringify it so it's no longer unique, then map it back to an array later. This should do the trick:

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


var unique = arr.map(cur =>JSON.stringify(cur))
  .filter(function(curr, index, self) {
    return self.indexOf(curr) == index;
  })
  .map(cur =>JSON.parse(cur))

console.log(unique);

Solution 3:

If you are ok to use a library, try lodash uniqWith. This will recursively find groups of arrays OR objects with the comparator of your choice: equal in your case.

var arrayofarrays = [ [1,1,2], [1,2,1], [1,1,2], [1,2,1], [2,1,1], [2,1,1] ]

const uniqarray = _.uniqWith(arrayofarrays, _.isEqual);

console.log(uniqarray) //=> [[1, 1, 2], [1, 2, 1], [2, 1, 1]]

Bonus: it works on array of objects too

var objects = [{ 'x'1'y': {b:1} }, { 'x'1'y': {b:1} }, 
               { 'x'2'y': {b:1} }, { 'x'1'y'2 }     ];

const uniqarray = _.uniqWith(objects, _.isEqual);

console.log(uniqarray) 
// => [{x: 1, y: {b: 1}}, {x: 2, y: {b: 1}}, {x: 1, y: 2}]

Solution 4:

You can subclass Set for more flexibility in storing objects by storing the result of calling JSON.stringify on added objects.

classObjectSetextendsSet{
  add(elem){
    returnsuper.add(typeof elem === 'object' ? JSON.stringify(elem) : elem);
  }
  has(elem){
    returnsuper.has(typeof elem === 'object' ? JSON.stringify(elem) : elem);
  }
}
let set = newObjectSet([[1,1,2],[1,2,1],[1,1,2],[1,2,1],[2,1,1],[2,1,1]]);
console.log([...set]);
console.log([...set].map(JSON.parse));//get objects back

Solution 5:

The fastest method I've found is:

const points = [
  [0,0],
  [100,100],
  [400,400],
  [200,200],
  [200,200],
  [200,200],
  [300,300],
  [400,400],
]

const uniquePoints = Array.from(
  newMap(points.map((p) => [p.join(), p])).values()
)

All of the methods in this thread are fast. This one is faster than the Set method, however, as we never need to convert the stringified array back into a array.

To find unique objects, replace p.join() with JSON.stringify(p).

Note

In my case, the method shown above turned out to be the wrong strategy, as I was only really needing to check against identical adjacent points. For example, the test array used above includes the value [400,400] two times, though these values are not consecutive. The method shown above would have removed the second instance, while the code below would have kept it.

points = points.filter(
    (point, i) =>
      i === 0 ||
      !(points[i - 1][0] === point[0] && points[i - 1][1] === point[1])
  )

Post a Comment for "Map/set To Maintain Unique Array Of Arrays, Javascript"