JavaScript中的元组集?

JavaScript中的元组集?,javascript,ecmascript-6,set,tuples,Javascript,Ecmascript 6,Set,Tuples,在JavaScript中实现坐标集的最佳方法是什么?我希望能够做到以下几点: let s=new Set(); s.add([1,1]); if (s.has([1,1])) // false, since these are different arrays 上述操作不起作用,因为集合存储的是对数组的引用,而不是内容。这可以通过字符串完成: let s=new Set(); s.add("1,1"); s.add("2,2"); console.log

在JavaScript中实现坐标集的最佳方法是什么?我希望能够做到以下几点:

let s=new Set();
s.add([1,1]);
if (s.has([1,1])) // false, since these are different arrays

上述操作不起作用,因为
集合
存储的是对数组的引用,而不是内容。

这可以通过字符串完成:

let s=new Set();
s.add("1,1");
s.add("2,2");
console.log(s.has("1,1"), s.has("1,2")); // true false

但是,我更愿意使用某种类型的数值元组来实现这一点,以避免重复的字符串转换逻辑。

为了更大的灵活性,您可以将
集子类化

类对象集扩展了对象集{
添加(元素){
返回super.add(typeof elem==“object”?JSON.stringify(elem):elem);
}
has(elem){
返回super.has(typeof elem=='object'?JSON.stringify(elem):elem);
}
}
设s=newobjectset();
s、 增加([1,1]);
console.log(s.has([1,1]))
日志(s.has([1,2,3]);
console.log([…s]);

log([…s].map(JSON.parse))//取回对象
如果我们可以假设元组是有限整数,那么它们可以被编码为浮点

class TupleSet extends Set{
    add(elem){
      return super.add((typeof elem === 'object' 
                        && Number.isSafeInteger(elem[0]) 
                        && Number.isSafeInteger(elem[1])) 
                        ? elem[0]+elem[1]/10000000 : elem);
    }
    has(elem){
      return super.has((typeof elem === 'object'
                        && Number.isSafeInteger(elem[0]) 
                        && Number.isSafeInteger(elem[1])) 
                        ? elem[0]+elem[1]/10000000 : elem);
    }
  }
  function TupleSetParse(elem){
     return (Number.isFinite(elem)?
        [Math.round(elem),Math.round((elem-Math.round(elem))*10000000)]:elem);
  }
  
  let s=new TupleSet();
  s.add([1,5]);
  s.add([1000000,1000000]);
  s.add([-1000000,-1000000]);
  console.log(s.has([1,5]));  // true
  console.log(s.has([1,2]));  // false
  console.log([...s].map(TupleSetParse));  
    // [ [ 1, 5 ], [ 1000000, 1000000 ], [ -1000000, -1000000 ] ]

当然,这是有限的范围。而且它对某些格式错误的输入很脆弱,因此应该添加额外的错误检查。然而,经过一些测试,这种方法在速度和内存使用方面仅比JSON.stringify方法好25%。因此,JSON是首选方法。

如果您只计划存储成对的坐标,另一种可能是使用映射(第一个坐标)和集合(第二个坐标)的组合

函数TupleSet(){
this.data=newmap();
this.add=函数([第一,第二]){
如果(!this.data.has(第一个)){
this.data.set(首先,new set());
}
this.data.get(第一)、add(第二);
归还这个;
};
this.has=函数([第一,第二]){
返回(
this.data.has(第一个)&&
this.data.get(第一个).has(第二个)
);
};
this.delete=函数([第一,第二]){
如果(!this.data.has)(第一个)||
!this.data.get(第一个).has(第二个)
)返回false;
this.data.get(第一)、delete(第二);
if(this.data.get(first).size==0){
本.数据.删除(第一);
}
返回true;
};
}
让mySet=newtupleset();
mySet.add([0,2]);
mySet.add([1,2]);
mySet.add([0,3]);
log(mySet.has([1,3]);
log(mySet.has([0,2]);
mySet.delete([0,2]);

log(mySet.has([0,2])这很好,谢谢。我仍然想知道是否有一种方法可以在没有字符串的情况下执行此操作,以避免时间/空间效率低下。@DavidXYZ没有任何更简单的方法。@DavidXYZ是否更喜欢使用哈希集之类的东西?set对象上的默认
.has()
查找物理上相同的对象,而不是具有相同属性的任何旧对象。因此,不能直接使用现有的
.has()
进行此操作。看起来hev的答案可能是你最好的选择。另一种选择(使用相同的
isSafeInteger
caveat)是使用配对功能,例如:和