35

Input:

[[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]]

The output I want:

[[-1,-1,2],[-1,0,1]]

Any other ideas except this one?

Thanks

Community
  • 1
  • 1
BAE
  • 8,550
  • 22
  • 88
  • 171
  • 1
    Any reason why we shouldn't close this as a duplicate of the question you yourself linked to? Did the solution in that question not work for you? – nnnnnn May 17 '17 at 03:05
  • Agreed. That looks like a pretty good solution. – Will Reese May 17 '17 at 03:06
  • 2
    @nnnnnn Because that's a horrible and slow approach? – Bergi May 17 '17 at 03:06
  • Its the semantics that are worrisome. Is identity really definable by `toString` for all values? – Aluan Haddad May 17 '17 at 03:07
  • @Bergi - But it's still the same requirement, right? – nnnnnn May 17 '17 at 03:07
  • 3
    If you're data is actually more complicated than just integers, you could use this method for comparison: http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript – Will Reese May 17 '17 at 03:07
  • @nnnnnn Maybe, the other question isn't as succinct - and it's not tagged [es6] either :-) – Bergi May 17 '17 at 03:14
  • `[[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]].filter((a, i) => x.findIndex(b => a[0]===b[0] && a[1]===b[1] && a[2]===b[2]) === i)` will work. Not sure about speed though. O(n^2) most likely. – david May 17 '17 at 03:14
  • Not sure what this has to do with es2015 so I removed the tag :p – Aluan Haddad May 17 '17 at 03:21
  • @BAE don't forget to accept best answer (by clicking on gray "check" button on its left side) – Kamil Kiełczewski Nov 28 '18 at 15:57

7 Answers7

32

You won't really get around stringifying the arrays, as that's the simplest (and reasonably fast) way to compare them by value. So I'd go for

Array.from(new Set(input.map(JSON.stringify)), JSON.parse)

See also Remove Duplicates from JavaScript Array for other approaches, though most of them will require two values to be comparable by ===.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    While I agree that this works, I'd be concerned about the 2nd and 3rd arguments that `JSON.stringify()` will receive from `.map()` interfering with it in some implementation, since the 2nd argument is supposed to be either `null` or a function, and the 3rd argument is supposed to be a number or a string. – Patrick Roberts Nov 28 '18 at 14:51
20

Magic

d.filter(( t={}, a=> !(t[a]=a in t) ));

I assume your input data are in array d. Explanation here.

let d = [[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]];

var r = d.filter((t={},a=>!(t[a]=a in t)));

console.log(JSON.stringify(r));
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
6

There's already a good utility for that, try Lodash, one of the function of it is _.uniqWith, with that function you can do the following.

<script src="/path/to/lodash.js"></script>
<script>
    var aa = [[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]];
    console.log(aa);
    console.log(_.uniqWith(aa,_.isEqual));
</script>
JMS786
  • 1,103
  • 2
  • 11
  • 22
2

You can create a hashMap and save values in it. This will always hold last value.

var data = [[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]]

var hashMap = {}

data.forEach(function(arr){
  // If your subArrays can be in any order, you can use .sort to have consistant order
  hashMap[arr.join("|")] = arr;
});

var result = Object.keys(hashMap).map(function(k){
  return hashMap[k]
})

console.log(result)
Rajesh
  • 24,354
  • 5
  • 48
  • 79
0

jsfiddle

Borrowing the array comparison code from this post

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}

var old = [[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]], n = [];

while(old.length) {
    var arr = old.shift(), matched = false;

  for(var i = 0, len = n.length; i < len; i++) {
    if (arr.equals(n[i])) {
        matched = true;
        break;
    }
  }
  if (!matched) {
    n.push(arr);
  }
}
Community
  • 1
  • 1
Will Reese
  • 2,801
  • 2
  • 15
  • 27
0
const removeDuplicates = (arr = []) => {
    const map = new Map();
    arr.forEach((x) => map.set(JSON.stringify(x), x));
    arr = [...map.values()];
    return arr;
};

console.log(
    removeDuplicates([
        [1, 1, 6],
        [1, 2, 5],
        [1, 7],
        [1, 2, 5],
        [1, 7],
        [2, 6],
    ])
);
// we can use simple JS object also to store unique elements  like { "[1, 1, 6]" : [1, 1, 6]  }
//resource - https://hackinbits.com/articles/how-to-iterate-a-map-in-javascript---map-part-2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 30 '22 at 09:30
-1

If you want to prevent duplicates in array during construction:

if (!arr.includes(subArray)) {
  arr.push(subArray)
}
Artur Müller Romanov
  • 4,417
  • 10
  • 73
  • 132