Можно ли использовать объект javascript "Set" для поиска элемента с определенным ключом? Что-то вроде того:
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let mySet = new Set(myObjects);
console.log(mySet.has({"name":"a"}));
Не таким образом, чтобы искать конкретный объект, который вы передаете, который не входит в набор.
Если ваша отправная точка представляет собой массив объектов, вам совсем не нужен Set
, просто Array.prototype.find
:
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let found = myObjects.find(e => e.name === "a");
console.log(found);
Если у вас уже есть Set
и хотите найти его на матч, вы можете использовать свой итератор, либо непосредственно через for-of
:
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let mySet = new Set(myObjects);
let found = undefined; // the '= undefined' is just for emphasis; that the default value it would have without an initializer
for (const e of mySet) {
if (e.name === "a") {
found = e;
break;
}
}
console.log(found);
... или косвенно через Array.from
(re) create (the) массив, а затем использовать find
:
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let mySet = new Set(myObjects);
let found = Array.from(mySet).find(e => e.name === "a");
console.log(found);
Если вам что-то нужно делать часто, вы можете дать ему функцию полезности:
const setFind = (set, cb) => {
for (const e of set) {
if (cb(e)) {
return e;
}
}
return undefined; // undefined' just for emphasis, 'return;'
// would do effectively th same thing, as
// indeed would just not having a 'return'
// at at all
}
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let mySet = new Set(myObjects);
let found = setFind(mySet, e => e.name === "a");
console.log(found);
Вы можете даже поставить это на Set.prototype
(убедитесь, что он не перечислим), но остерегайтесь противоречия с будущими дополнениями к Set
(например, я бы не удивился, если Set.prototype
получил метод find
в какой-то момент).
Вам может просто понадобиться набор имен:
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let map = new Set(myObjects.map(el=>el.name));
console.log(map.has("a"));
Если вы хотите получить объект по имени, для чего предназначена карта:
let myObjects = [{"name":"a", "value":0}, {"name":"b", "value":1},{"name":"c", "value":2}];
let map = new Map(myObjects.map(el=>[el.name,el]));
console.log(map.get("a"));
Map
работает, для этого и let mySet = new Set(myObjects.map(e => e.name)); console.log(mySet.has("a"));
набор : let mySet = new Set(myObjects.map(e => e.name)); console.log(mySet.has("a"));
(если мы собираемся решить это таким образом).
Если вы хотите сделать это с помощью Set, то объект, который вы ищете, должен быть тем же самым объектом, который был добавлен, а не анонимным объектом.
Таким образом, вы могли бы добиться того, что искали, если бы оно было настроено так:
let myObject = {"name": "a", "value": 0};
let set = new Set([myObject]);
console.log(set.has(myObject));
Это связано с тем, что set.has()
использует SameValueZero()
под капотом.
Вот спецификация для set.has()
: http://www.ecma-international.org/ecma-262/6.0/#sec-set.prototype.has
И для SameValueZero()
: http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
Короткий ответ - нет. Set.has
работает с равенством объектов, и каждый объект в списке уникален - поэтому, когда вы передаете новый объект в .has
он не вернет true
, даже если он имеет одинаковые ключи и значения.
Вы всегда можете отфильтровать исходный список, и если результирующий список имеет длину больше нуля, ваш объект будет содержаться внутри.
const containsObjectWithName = ({ name }) =>
!!myObjects
.filter((obj) => obj.name === name)
.length;
containsObjectWithName({ name: 'a' }); // true
Set
имеет сложность O (1).