Javascript поиск ключа объекта в наборе

1

Можно ли использовать объект 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"}));
Теги:
key
set
search

4 ответа

5
Лучший ответ

Не таким образом, чтобы искать конкретный объект, который вы передаете, который не входит в набор.

Если ваша отправная точка представляет собой массив объектов, вам совсем не нужен 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 в какой-то момент).

  • 0
    Спасибо за ваш ответ, мой вопрос был просто из любопытства, так как я где-то читал, что поиск в объекте Set имеет сложность O (1).
  • 0
    проверка, есть ли в нем что-то ! == поиск
Показать ещё 2 комментария
5

Вам может просто понадобиться набор имен:

 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"));
  • 1
    Пока 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")); (если мы собираемся решить это таким образом).
2

Если вы хотите сделать это с помощью 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

  • 0
    Это не делает то, что спросил ОП. Совершенно очевидно, что у вопроса есть два отдельных объекта (один в массиве, а другой ищется), а не один объект.
1

Короткий ответ - нет. Set.has работает с равенством объектов, и каждый объект в списке уникален - поэтому, когда вы передаете новый объект в .has он не вернет true, даже если он имеет одинаковые ключи и значения.

Вы всегда можете отфильтровать исходный список, и если результирующий список имеет длину больше нуля, ваш объект будет содержаться внутри.

const containsObjectWithName = ({ name }) => 
  !!myObjects
    .filter((obj) => obj.name === name)
    .length;

containsObjectWithName({ name: 'a' });  // true

Ещё вопросы

Сообщество Overcoder
Наверх
Меню