ES6有一个新的Set数据结构,用于存储多组唯一对象。然而,它基于对象引用而不是值比较。据我所知,这使得无法在没有字符串化的情况下拥有一组数字。
例如,在Chrome控制台中键入内容(需要Chrome 38 +):
> var s = new Set();
< undefined
> s.add([2, 3]);
< Set {[2, 3]}
> s.has([2, 3])
< false <--- was hoping for 'true'
这似乎是设计上的:因为我将不同的数组[2, 3]
传递给has()
,所以它返回false,因为虽然内容相同,但它只是看起来在对象引用,我分配了一个新的不同的数组传递给has()
。我需要存储对传递给add()
的原始数组的引用,以便与has()
一起检查,但这并不总是可行的。例如,如果数字对代表坐标,我可能需要检查该集合是否具有[obj.x, obj.y]
,但由于它分配了一个新数组,因此总是返回false。
解决方法是将数组和键键入字符串,例如&#34; 2,3&#34;代替。然而,对于像游戏引擎这样对性能敏感的东西,如果每个set访问都需要进行字符串分配并转换和连接数字字符串,这是很不幸的。
ES6是否提供任何功能来解决此问题而无需进行字符串化,或者ES7是否有任何功能可以提供帮助?
答案 0 :(得分:3)
正如您所指出的那样[2, 3] === [2, 3]
是false
,这意味着你不能像这样使用 Set ;然而, Set 真的是最适合你的选择吗?
你可能会发现使用这样的两级数据结构对你来说会更好
var o = {};
function add(o, x, y) {
if (!o[x]) o[x] = {};
o[x][y] = true;
}
function has(o, x, y) {
return !!(o[x] && o[x][y]);
}
function del(o, x, y) {
if (!o[x]) return;
delete o[x][y];
// maybe delete `o[x]` if keys.length === 0
}
如果您想使用 ES6
,您可以使用指向集的 Map 执行类似的结构答案 1 :(得分:0)
ES7有什么功能可以提供帮助吗?
ECMAScript 7中有一项建议添加Value Objects。基本上,它是一个新的不可变数据类型,其中相同的值对象按值进行比较,而不是通过引用进行比较。
根据实施的价值对象类型和/或if custom ones can be defined,它们可能会解决此问题。
答案 2 :(得分:0)
这里超级晚,但是由于ES7毕竟还没有解决问题,而且我注意到如果其他人在权衡利弊时没有特别提及,则有两种方法(第一种方法不能解决,第二种可能): / p>
对于执行大量计算的任务而言,它并不是最佳选择,但是您可以使用使用模板文字的串联字符串来实现可表达性,例如
set.add(`${x}_${y}`);
和检索:
set.get(`${i}_${j}`);
(请注意,我故意避免使用,
作为分隔符,因为在某些领域(例如金融领域)可能会造成混淆)。
可以做的另一件事是,如果知道边界,例如抓住第一维的宽度来展平数组。
set.get(x+y*width);
或者如果您通常使用较小的数字(不超过10,000s)并且不知道最大宽度是多少,则可以使用任意的非常大的数字。最佳效果稍差一些,但仍比字符串concat好:
set.get(x+y*Math.floor(Math.sqrt(Number.MAX_SAFE_INTEGER)));
同样,这些并不是完美的解决方案,因为它们无法处理x*y
可能超过Number.MAX_SAFE_INTEGER
的大量数字,但是它们是工具箱中的某些东西,不需要知道固定的数组大小。