简体   繁体   中英

How to find existence of an array in a set?

Since set in Javascript is able to take object, including arrays, how do I find the existence of an array list in a set?

I tried the following code:

var sello = new Set();
sello.add(["a","b"])
console.log(sello.has(["a","b"])) // outputs false

I'm assuming

sello.has(["a","b"])

should have output true since I've added the exact array in the set sello . Am I missing out some falsy truthy thing or any logical error?

Note:

  • I'm not looking to match only the character "a" and/or "b" , I'm looking to match the whole array ["a","b"] .

  • I'm looking to match the array. I just need the content to be the
    same, the elements doesn't have to be the same order.

What you're trying to do won't work because in Javascript you can't compare arrays like that, even if they have the same values. This is because arrays are reference types, not value types, and for reference types Javascript determines whether they are equal or not based on whether they are referencing the same object (ie the same place in memory). For instance, just try:

console.log(['a','b'] == ['a','b']); // false

Despite having the same values, each array is a new reference, so they are not equal to each other.

In contrast, the comparison in the code below does involve arrays referencing the same object on both sides of the equation:

let a = ['a','b'];
console.log(a == a); // true

And therefore:

let sello = new Set();
sello.add(a);
console.log(sello.has(a)); // true

To remedy this, you'll want to create a function that compares arrays based on their values. You can first check if the arrays have the same length. If not, then they're not equal. You can then loop through the items in each and see if any are different for any given position. If so, they're not equal. Otherwise, assuming you're dealing with a flat array of primitive values (no nested objects of reference type), then the arrays are equal. This is what I do in 'isEqual' below:

function isEqual(x,y) {
    if (x.length != y.length)
        return false;
    for (let i in x)
        if (x[i] != y[i])
            return false;
    return true;
}

Test it if you like:

console.log(isEqual(['a','b'],['a','b'])); // true

Now, unfortunately, Set.has() doesn't accept a function, so we can't use it with isEqual . But you can just loop through the values of the set. If creating a one-liner is the goal, the best way I have found to do this is to convert the set to an array and use the some method. some accepts a function that evaluates each row, and if it returns true for any row, then the result is true, else false.

console.log(
    [...sello].some(item => isEqual(item, ['a','b']))
); 
// true

In JavaScript, Arrays are Objects, and no two separate Objects are ever considered equal.

MDN shows the same error with a standard object:

var set1 = new Set();
var obj1 = {'key1': 1};
set1.add(obj1);

set1.has(obj1);        // returns true
set1.has({'key1': 1}); // returns false because they are different object references


The easiest way to use .has with an Object (such as an Array) is to get a reference to the Object, like:

 let sello = new Set(); let myArray = ["a","b"]; sello.add(myArray); console.log(sello.has(myArray)); // outputs true 


If you can't get a reference to the Array, you'll probably need to check each Array in the Set by iterating through the Array and comparing each element individually.

You could do this more concisely, but this explicit example clarifies the process:

 // Declares and populates the Set let sello = new Set(); sello.add( ["a", "c"] ); sello.add( ["a", "b"] ); sello.add( ["b", "c"] ); // Tests the `setHasArray` function let result = setHasArray(sello, ["a", "b"]); console.log(`result: ${result}`); // Defines the `setHasArray` function function setHasArray(theSet, arrayToMatch){ // Creates a flag let isMatch = false; // Iterates through the Set for (let member of theSet){ // Logs the Array we're about to compare elements of console.log("comparing:", member); // Makes sure this member is an Array before proceeding if(Array.isArray(member)){ // Tentatively sets the flag to `true` isMatch = true; // Iterates through the Array, comparing each value arrayToMatch.forEach( (_, index) => { // Logs the comparison for the current value console.log( member[index] + (member[index] === arrayToMatch[index] ? " === " : " !== ") + arrayToMatch[index] ); // Even one non-matching element means the Array doesn't match if(member[index] !== arrayToMatch[index]){ console.log("Rats! Looked like a possible match there for a second."); isMatch = false; } }); // Logs a successful match for the current member of the Set if(isMatch){ console.log("Found a match!") // Stops checking Arrays lest the flag get reset and give us a false negative break; } } } // Returns our result return isMatch; } 

(See .forEach on MDN if you're not familiar with this method.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM