Как использовать метод include в lodash, чтобы проверить, находится ли объект в коллекции?

146

lodash позволяет мне проверять членство основных типов данных с помощью includes:

_.includes([1, 2, 3], 2)
> true

Но следующее не работает:

_.includes([{"a": 1}, {"b": 2}], {"b": 2})
> false

Это сбивает меня с толку, потому что следующие методы, которые ищут в коллекции, кажется, делают хорошо:

_.where([{"a": 1}, {"b": 2}], {"b": 2})
> {"b": 2}
_.find([{"a": 1}, {"b": 2}], {"b": 2})
> {"b": 2}

Что я делаю не так? Как проверить членство объекта в коллекции с помощью includes?

изменить: вопрос был изначально для для lodash версии 2.4.1, обновлен для lodash 4.0.0

Conrad.Dean
источник
7
_.containsбыл удален в lodash v4 - используйте _.includesвместо этого
Billy Moon
@BillyMoon woops! да, вы правы, lodash v4.0.0 (выпущен 2016-01-12) удаляет containsпсевдоним. Я
обновлю

Ответы:

222

includes(Прежнее название containsи include) метод сравнивает объекты по ссылке (или , точнее, с ===). Поскольку два литерала объекта {"b": 2}в вашем примере представляют разные экземпляры, они не равны. Примечание:

({"b": 2} === {"b": 2})
> false

Однако это будет работать, потому что есть только один экземпляр {"b": 2}:

var a = {"a": 1}, b = {"b": 2};
_.includes([a, b], b);
> true

С другой стороны, методы where(устаревшие в v4) и findметоды сравнивают объекты по их свойствам, поэтому им не требуется равенство ссылок. В качестве альтернативы includesвы можете попробовать some(также с псевдонимом any):

_.some([{"a": 1}, {"b": 2}], {"b": 2})
> true
PSWG
источник
12

Дополняя ответ на p.s.w.g, вот три способа достижения этой цели использования lodash 4.17.5, без использования _.includes() :

Допустим, вы хотите добавить объект entryв массив объектов numbers, только если он entryеще не существует.

let numbers = [
    { to: 1, from: 2 },
    { to: 3, from: 4 },
    { to: 5, from: 6 },
    { to: 7, from: 8 },
    { to: 1, from: 2 } // intentionally added duplicate
];

let entry = { to: 1, from: 2 };

/* 
 * 1. This will return the *index of the first* element that matches:
 */
_.findIndex(numbers, (o) => { return _.isMatch(o, entry) });
// output: 0


/* 
 * 2. This will return the entry that matches. Even if the entry exists
 *    multiple time, it is only returned once.
 */
_.find(numbers, (o) => { return _.isMatch(o, entry) });
// output: {to: 1, from: 2}


/* 
 * 3. This will return an array of objects containing all the matches.
 *    If an entry exists multiple times, if is returned multiple times.
 */
_.filter(numbers, _.matches(entry));
// output: [{to: 1, from: 2}, {to: 1, from: 2}]

Если вы хотите вернуть a Boolean, в первом случае вы можете проверить возвращаемый индекс:

_.findIndex(numbers, (o) => { return _.isMatch(o, entry) }) > -1;
// output: true
Михай
источник