Набор, который я использую выше, полезен только для примитивов.
Это неверно, он отлично работает для объектов. Проблема состоит в том, что различные объекты с одинаковыми свойствами и значениями свойств не равны, поэтому выполнение set.add({"language": "ecmascript"});
дважды добавляет два неравных объекта в набор (оба с одинаковыми именем и значением свойства).
Если вы добавляете один и тот же объект более одного раза, он не будет добавлен во второй раз:
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
. (Хотя это не сработает, если вы хотите использовать символьные ключи как часть определения равенства.) Например, если вы рассматриваете только собственные свойства:
const key = JSON.stringify(Object.getOwnPropertyNames(object).sort());
Значением для записи может быть либо просто массив объектов с теми ключами, по которым вы выполняете линейный поиск, либо секунда Map
, заданная каким-то хэшем значений свойств, в зависимости от того, сколько объектов вам нужно справиться ...
В комментариях я спросил:
Вам нужно обрабатывать объекты только с сериализуемыми 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