Storing arrays in ES6 Set and accessing them by value

空扰寡人 提交于 2021-01-19 16:19:50

问题


Is there a simple way to verify that an ES6 Set contains a value that is a particular array? I'd like a solution that doesn't require me to use a reference:

var set = new Set();

var array = [1, 2];
set.add(array);
set.has(array); // true

set.add([3, 4]);
set.has([3, 4]); // false

So far my solution is to store everything as a string, but this is annoying:

set.add([3, 4].toString());
set.has([3, 4].toString()); // true

回答1:


No there is not.

A Set works on objects and primitives and is useful for preventing identical primitives and re-adding the same object instance.

Each array is their own object, so you can actually add two different arrays with the same values.

var set = new Set();
set.add([3, 4]);
set.add([3, 4]);
console.log(set.size);//2

Additionally, there's nothing to prevent an object from being changed once in a set.

var set = new Set();
var a1 = [3, 4];
var a2 = [3, 4];
set.add(a1);
set.add(a2);
a2.push(5);
for (let a of set) {
    console.log(a);
}
//Outputs:
// [3, 4]
// [3, 4, 5]

A set does not have a mechanism for checking the values of objects in a set. Since the value of an object could change at any time, it wouldn't be much more efficient than simply looping over them yourself.

The functionality you are looking has been kicked around in various ECMAScript proposals, however it does not appear to be coming anytime soon.




回答2:


Apparently, it doesn't look like set.has() will check for Array Elements like that. They are added, however:

var set = new Set([1, 2]);
set.add([3, 4]);
console.log(Array.from(set));



回答3:


It's not using a Set, but may solve your problem.

If you want to make sure that an array can only exist in a collection once, and you want instant lookups you can use a hash by abusing its keys. They do not necessarily need a value. You can set them to undefined, to true, or something else if it makes you sleep better at night 😛.

Inspired by: javascript search array of arrays

It is halfway tempting to make a wrapper, but it is also simple enough to handle a small job.

const hash = {};

hash[[1, 2, 3]] = undefined;
hash[[3, 4]] = undefined;
hash[[3, 4]] = undefined;

console.log({hash});
console.log("hash has [3, 4]?", hash.hasOwnProperty([3, 4]));

For me, this will work fine, because I am checking if a coordinate exists in a collection. Unfortunately from this stackoverflow it seems that Set cannot be the answer to this problem.

Coincidentally it seems to implicitly solve your problem of not calling toString on the array which this seems to do under the hood. Personally I don't care for hash.hasOwnProperty.

A More Elegant Option

You could even write a wrapper to your code like:

class ArraySet extends Set {
  add(arr) {
    super.add(arr.toString());
  }
  has(arr) {
    return super.has(arr.toString());
  }
}

const arraySet = new ArraySet();

arraySet.add([1, 2]);
arraySet.add([3, 4]);
arraySet.add([3, 4]);

console.log("ArraySet has [3, 4]?", arraySet.has([3, 4]));


来源:https://stackoverflow.com/questions/29760644/storing-arrays-in-es6-set-and-accessing-them-by-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!