Javascript "Set" 对象和数组
Javascript "Set" for Objects and Arrays
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 仅对基元有用。
The Set I'm using above is only useful for primitives.
这是不正确的,它适用于对象。问题在于具有相同属性和 属性 值的不同对象不相等,因此执行 set.add({"language": "ecmascript"});
两次会将两个不相等的对象添加到集合中(两者都具有相同的 属性 名称和值)。
如果您多次添加同一个对象,将不会添加第二次:
const set = new Set();
const obj = {"language": "ecmascript"};
set.add(obj);
set.add(obj);
console.log(set.size); // 1
Does Javascript have a built-in type for...
如果您希望具有相同属性和值的对象被视为相等,则否。您需要能够指定比较操作,并且 JavaScript 中没有内置的 Set
可让您定义要使用的比较操作。
显然,您可以创建一个。作为起点,我可能会使用 Map
键控对象的属性名称,排序并通过 JSON.stringify
转换为字符串。 (虽然如果你想将 Symbol 键作为相等定义的一部分,那将不起作用。)例如,如果你只考虑自己的属性:
const key = JSON.stringify(Object.getOwnPropertyNames(object).sort());
一个条目的值可以只是一个对象数组,这些对象具有您进行线性搜索的那些键,或者是第二个 Map
由 [=53= 的某种哈希键控] 值,具体取决于您需要处理的对象数量...
在评论中,我问:
Do you only need to handle objects with JSON-serializable values?
你回答了:
I have a bunch of objects that are already serialized, but there are duplicates that I'd like to eliminate and then re-serialize.
是的,如果你不介意重新序列化,你可以使用 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
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 仅对基元有用。
The Set I'm using above is only useful for primitives.
这是不正确的,它适用于对象。问题在于具有相同属性和 属性 值的不同对象不相等,因此执行 set.add({"language": "ecmascript"});
两次会将两个不相等的对象添加到集合中(两者都具有相同的 属性 名称和值)。
如果您多次添加同一个对象,将不会添加第二次:
const set = new Set();
const obj = {"language": "ecmascript"};
set.add(obj);
set.add(obj);
console.log(set.size); // 1
Does Javascript have a built-in type for...
如果您希望具有相同属性和值的对象被视为相等,则否。您需要能够指定比较操作,并且 JavaScript 中没有内置的 Set
可让您定义要使用的比较操作。
显然,您可以创建一个。作为起点,我可能会使用 Map
键控对象的属性名称,排序并通过 JSON.stringify
转换为字符串。 (虽然如果你想将 Symbol 键作为相等定义的一部分,那将不起作用。)例如,如果你只考虑自己的属性:
const key = JSON.stringify(Object.getOwnPropertyNames(object).sort());
一个条目的值可以只是一个对象数组,这些对象具有您进行线性搜索的那些键,或者是第二个 Map
由 [=53= 的某种哈希键控] 值,具体取决于您需要处理的对象数量...
在评论中,我问:
Do you only need to handle objects with JSON-serializable values?
你回答了:
I have a bunch of objects that are already serialized, but there are duplicates that I'd like to eliminate and then re-serialize.
是的,如果你不介意重新序列化,你可以使用 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