38

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

10
  • 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? Commented May 17, 2017 at 3:05
  • Agreed. That looks like a pretty good solution. Commented May 17, 2017 at 3:06
  • 2
    @nnnnnn Because that's a horrible and slow approach? Commented May 17, 2017 at 3:06
  • Its the semantics that are worrisome. Is identity really definable by toString for all values? Commented May 17, 2017 at 3:07
  • 3
    If you're data is actually more complicated than just integers, you could use this method for comparison: stackoverflow.com/questions/7837456/… Commented May 17, 2017 at 3:07

8 Answers 8

36

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 ===.

Sign up to request clarification or add additional context in comments.

1 Comment

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.
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));

3 Comments

Sometimes I have to declare t first, sometimes I don't, so weird.
looks like its strict mode when it yells about a referenceerror for t
This relies on string coercion of arrays, which fails for cases like [ [ "a", "b" ], [ "a,b" ] ].
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>

Comments

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)

3 Comments

This fails for [ [ "a", "b" ], [ "a|b" ] ].
If you change input structure, any algorithm will fail.
The input structure is the same.
1
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

1 Comment

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.
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);
  }
}

2 Comments

Why would one use instanceof over Array.isArray? I am just curious.
There's not really any difference. Refer to stackoverflow.com/questions/22289727/…
0

We can can create new uniqueArray based on our original arrayWithDuplicates using reduce method:

const arrayWithDuplicates = [[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,-1,2],[-1,0,1],[-1,0,1]];

const uniqueArray = arrayWithDuplicates.reduce((acc, curr) => {
  if (!acc.some(arr => arr.length === curr.length && arr.every((val, i) => val === curr[i]))) {
    acc.push(curr);
  }
  return acc;
}, []);

console.log(uniqueArray);

Comments

-1

If you want to prevent duplicates in array during construction:

if (!arr.includes(subArray)) {
  arr.push(subArray)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.