【问题标题】:Javascript "Set" for Objects and Arrays对象和数组的 Javascript“设置”
【发布时间】:2019-09-07 16:38:46
【问题描述】:

Javascript 是否有一个内置类型来制作数据对象和数组的集合?

let set = new Set();
set.add({"language": "ecmascript"});
set.add({"language": "ecmascript"});
set.add({"language": "ecmascript"});
set.add({"language": "ecmascript"});
set.add([1,2,3]);
set.add([1,2,3]);
set.add([1,2,3]);
set.add([1,2,3]);
console.log(set);

我上面使用的 Set 只对原语有用。

【问题讨论】:

  • 这个的用例是什么?
  • 您可以使用 Set 并使用 JSON.stringify 方法转换数组和对象,然后使用 JSON.parse 恢复其原始形式。
  • Set 的文档包括whether primitive values or object references.,所以请在此处解释为什么 Set 对您没有用处。真正的问题是保持对对象的引用,以便您可以比较具有相同属性和值的两个不同对象吗?
  • @Petros :这是一种合理的技术,但是对于每个序列化,属性名称的顺序必须完全相同。 JSON.stringify 是否按字母顺序排列它们?
  • @Petros - 这很脆弱,因为JSON.stringify 遵循 ES2015 属性顺序,该顺序由属性添加到对象的时间定义。所以{a:1,b:2}{b:2,a:1} 按照规范序列化为不同的 JSON 字符串。

标签: javascript set ecmascript-next


【解决方案1】:

我上面使用的 Set 只对原语有用。

这是不正确的,它适用于对象。问题是具有相同属性和属性值的不同对象不相等,因此执行两次set.add({"language": "ecmascript"}); 会将两个不相等的对象添加到集合中(都具有相同的属性名称和值)。

如果你多次添加 same 对象,它不会被添加第二次:

const set = new Set();
const obj = {"language": "ecmascript"};
set.add(obj);
set.add(obj);
console.log(set.size); // 1

Javascript 是否有内置类型用于...

如果您希望将具有相同属性和值的对象视为相等,那么不。您需要能够指定比较操作,并且 JavaScript 中没有内置的 Set 可以让您定义要使用的比较操作。

显然,您可以创建一个。作为一个起点,我可能会使用Map,它以对象上的属性名称为键,通过JSON.stringify 排序并转换为字符串。 (尽管如果您想将 Symbol 键作为相等定义的一部分,这将不起作用。)例如,如果您只考虑自己的属性:

const key = JSON.stringify(Object.getOwnPropertyNames(object).sort());

条目的值可能只是一个对象数组,其中包含您对其进行线性搜索的那些键,也可能是第二个Map,由某种属性值的哈希键控,具体取决于对象的数量你需要处理...


在cmets中,我问:

您只需要处理具有 JSON 可序列化值的对象吗?

你回答:

我有一堆已经序列化的对象,但有一些重复我想删除然后重新序列化。

是的,如果您不介意重新序列化,可以使用Set,如果您想跳过重新序列化部分,可以使用Map

const unique = new Map();
for (const source of serializedObjects) {
    const sourceObject = JSON.parse(source); // Or parse from whatever serialization it is
    // Build object adding properties in alpha order for stability
    const keyObj = {};
    for (const key of Object.keys(sourceObject).sort()) {
        keyObj[key] = sourceObject[key];
    }
    // Save it using JSON.stringify, which uses ES2015 property order
    map.set(JSON.stringify(keyObj), source);
}
const uniqueSourceStrings = [...map.values()];

或者对于反序列化的对象本身:

const unique = new Map();
for (const source of serializedObjects) {
    const sourceObject = JSON.parse(source); // Or parse from whatever serialization it is
    // Build object adding properties in alpha order for stability
    const keyObj = {};
    for (const key of Object.keys(sourceObject).sort()) {
        keyObj[key] = sourceObject[key];
    }
    // Save it using JSON.stringify, which uses ES2015 property order
    map.set(JSON.stringify(keyObj), sourceObject); // <=================== changed
}
const uniqueSourceObject = [...map.values()];
//    ^^================================================================== changed

【讨论】:

  • 顺便说一句,我在亚马逊 (proof) 上预购了您的 book。我不时收到通知说发布已延迟。进展如何?
  • ...几乎...那里... :-) 我认为,出版商的最新发布日期修订版是故意悲观的。但说到这本书,我要回去编辑土地了。 (更新了答案,顺便说一句。)(描述也过时了,他们告诉我他们会更新它,但是......这本书涵盖了 ES2019。)
  • 嗯,我很期待。别再做完美主义者了,释放那个东西。让您的读者报告错别字,并在第 2 版中更正这些内容;)
  • @LonnieBest - 将完美抛诸脑后。拍摄足够。 ;-)
  • 哈!好吧,我敢肯定会是这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多