Map/Set to maintain unique array of arrays, Javasc

2020-07-07 11:07发布

问题:

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 permutations of [1,1,2]

Actual : [[1,1,2],[1,2,1],[1,1,2],[1,2,1],[2,1,1],[2,1,1]]
Expected : [[1,1,2],[1,2,1],[2,1,1]]

Approaches I tried:

  1. Array.Filter: Doesn't work because arrays are object and each value in uniqueArrComparer is a unique object reference to that array element.
function uniqueArrComparer(value, index, self) {
  return self.indexOf(value) === index;
}

result.filter(uniqueArrComparer)
  1. Set/Map: Thought I can build a unique array set but it doesn't work because Set internally uses strict equality comparer (===), which will consider each array in this case as unique.
    We cannot customize object equality for JavaScript Set

  2. Store each array element as a string in a Set/Map/Array and build an array of unique strings. In the end build array of array using array of unique string. This approach will work but doesn't look like efficient solution.

Working solution using Set

let result = new Set();

// Store [1,1,2] as "1,1,2"
result.add(permutation.toString());

return Array.from(result)
  .map(function(permutationStr) {

    return permutationStr
      .split(",")
      .map(function(value) {

        return parseInt(value, 10);
      });
  });

This problem is more of a learning exercise than any application problem.

回答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  = new Set(arr.map(JSON.stringify));
let arr2 = Array.from(set).map(JSON.parse);

console.log(arr2)



回答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);