Comment utiliser la méthode includes dans lodash pour vérifier si un objet est dans la collection?

146

lodash me permet de vérifier l'appartenance aux types de données de base avec includes:

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

Mais ce qui suit ne fonctionne pas:

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

Cela me trouble car les méthodes suivantes qui recherchent dans une collection semblent très bien fonctionner:

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

Qu'est-ce que je fais mal? Comment vérifier l'appartenance d'un objet dans une collection avec includes?

edit: la question était à l'origine pour lodash version 2.4.1, mise à jour pour lodash 4.0.0

Conrad.Dean
la source
7
_.containsa été supprimé dans lodash v4 - à utiliser à la _.includesplace
Billy Moon
@BillyMoon woops! ouais vous avez raison, lodash v4.0.0 (publié le 12/01/2016) supprime l' containsalias. Je vais mettre à jour ceci
Conrad.Dean

Réponses:

222

La méthode includes(anciennement appelée containsand include) compare les objets par référence (ou plus précisément avec ===). Étant donné que les deux littéraux d'objet de {"b": 2}dans votre exemple représentent des instances différentes , ils ne sont pas égaux. Remarquer:

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

Cependant, cela fonctionnera car il n'y a qu'une seule instance de {"b": 2}:

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

D'autre part, les méthodes where(obsolète dans la v4) et les findméthodes comparent les objets par leurs propriétés, de sorte qu'elles ne nécessitent pas d'égalité de référence. Au lieu de cela includes, vous pouvez essayer some(également aliasé any):

_.some([{"a": 1}, {"b": 2}], {"b": 2})
> true
pswg
la source
12

Pour compléter la réponse p.s.w.g, voici trois autres moyens d'y parvenir en utilisant lodash 4.17.5, sans utiliser _.includes() :

Supposons que vous souhaitiez ajouter un objet entryà un tableau d'objets numbers, uniquement s'il entryn'existe pas déjà.

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}]

Si vous souhaitez renvoyer un Boolean, dans le premier cas, vous pouvez vérifier l'index qui est renvoyé:

_.findIndex(numbers, (o) => { return _.isMatch(o, entry) }) > -1;
// output: true
Mihai
la source