Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/472.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Javascript集不做唯一的对象?_Javascript - Fatal编程技术网

为什么Javascript集不做唯一的对象?

为什么Javascript集不做唯一的对象?,javascript,Javascript,集合应该包含唯一的对象,但它不适用于javascript中的对象 var set = new Set() <- undefined set.add({name:'a', value: 'b'}) <- Set {Object {name: "a", value: "b"}} set.add({name:'a', value: 'b'}) <- Set {Object {name: "a", value: "b"}, Object {name: "a", value: "b"}}

集合应该包含唯一的对象,但它不适用于javascript中的对象

var set = new Set()
<- undefined
set.add({name:'a', value: 'b'})
<- Set {Object {name: "a", value: "b"}}
set.add({name:'a', value: 'b'})
<- Set {Object {name: "a", value: "b"}, Object {name: "a", value: "b"}}

这是为了获得sm.p的唯一列表。如果你正在寻找一个深度唯一集,你可以自己创建一个深度集,通过扩展原始的“集”,如下所示:

function DeepSet() {
    //
}
DeepSet.prototype = Object.create(Set.prototype);
DeepSet.prototype.constructor = DeepSet;
DeepSet.prototype.add = function(o) {
    for (let i of this)
        if (deepCompare(o, i))
            throw "Already existed";
    Set.prototype.add.call(this, o);
};

这很幼稚,我相信有更好的方法来获取唯一数据(比如让数据库查询返回唯一数据,但这取决于数据库),但是您可以在插入对象之前检查对象是否已经在集合中

var m = await(M.find({c: cID}).populate('p')) //database call
var p = new Set();
m.forEach(function(sm){
    if(!p.has(sm.p)) p.add(sm.p)
})
var m=await(m.find({c:cID}).populate('p')//数据库调用 var p=新集合(); m、 forEach(函数(sm){ 如果(!p.has(sm.p))p.add(sm.p)
})您可以使用地图。如果需要基于键的唯一值。对我来说,我想从对象数组中进行唯一的选择

let cats = [
    { category: 6 },
    { brand: 'purina' },
    { category: 5 },
    { category: 5 },
    { brand: 'purina' }];

var myMap = new Map();

cats.forEach(object => {
    for (const key in object) {
      myMap.set(key, object[key])
    }
})
console.log(myMap) //Map { 'category' => 5, 'brand' => 'purina' }

这里类别和品牌不再重复

好吧,Javascript集合不存储唯一的对象,因为每个对象都有自己的引用。因此,Set将只存储唯一的值,以便它处理两个或更多对象具有相同的值,并且它们的引用不同

范例-

var set = new Set();

set.add({ id: 1 });
set.add({ id: 2 });
set.add({ id: 3 });

// Every object has different reference
var d = { id: 4 };

set.add(d); 
set.add(d);

for (const item of set) {
    console.log(item);
}

// Output : 1 2 3 4
注意:解决方案是可以为同一对象创建引用 并添加到集合中,如上面我所做的示例


另一个选项是可以使用JSON.stringify()保持对象的唯一性,这样它就可以与字符串而不是对象引用进行比较

        set.add(JSON.stringify({name:'a', value: 'b'}))
然后在格式化所有内容之后,您可以将这些行解析回一个数组,如

    const formattedSet = [...set].map(item) => {
      if (typeof item === 'string') return JSON.parse(item);
      else if (typeof item === 'object') return item;
    });

根据JoeYichong的帖子,这里有一个建议,可以扩展打字脚本的设置

导出类DeepSet扩展集{
加(o:任何){
为了(让我来说说这个)
如果(这是(o,i))
归还这个;
super.add.call(this,o);
归还这个;
};
私人深度比较(o:any,i:any){
返回JSON.stringify(o)==JSON.stringify(i)
}
}

“我得到的事实是,它们是具有相同值的不同对象”-确切地说。它们是不同的对象。即使它们最初具有唯一的属性值,在添加到集合中后,它们也可以被修改为具有相同的属性值。@nnnnnn那么,如何实现我所寻找的具有唯一值的一组对象呢?(我也会接受一个唯一对象值数组)这可能会有帮助。@MattWestlake,很可能您不想将对象用作集合的键,而是希望使用带有排序键的JSON序列化。如果您正在执行数据库操作,您不能让数据库查询首先返回唯一的结果吗?数据库擅长于这类事情。这是添加这种行为的一个很好的方法。不幸的是,没有本地的
deepCompare
方法
DeepSet
必须由我们自己实现,就像我们必须自己实现
deepCompare
方法一样。这有点违背了使用集合的目的,也可能只是使用数组。此注释应为-1。如果要检查Set是否在0(n)处存在,则使用Set没有意义。另外,这并不是“幼稚的”,我有一个React应用程序,其中使用像Set这样的数据结构(如果我们能用Java或C#那样的正确方式实现它)将是我最好的选择)这将导致不必要的复杂性和不必要的副作用,通常最后一个总是赢的解决方案需要考虑顺序。不能信任JSON.stringify()每次都以相同的顺序给出键的结果。除此之外,还有许多值没有正确地字符串化,例如无穷大、NaN和递归对象。字符串化某些类型值的有效点。Symbol()和第一类函数也将被删除。在一些罕见的情况下,顺序也可能被打乱,如果这对您很重要,您可以执行类似于
set.add(JSON.stringify(obj,Object.keys(obj.sort()))
的操作来保留顶级键的顺序。看见
        set.add(JSON.stringify({name:'a', value: 'b'}))
    const formattedSet = [...set].map(item) => {
      if (typeof item === 'string') return JSON.parse(item);
      else if (typeof item === 'object') return item;
    });