Como uso o método includes no lodash para verificar se um objeto está na coleção?

146

O lodash permite verificar a associação de tipos de dados básicos com includes:

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

Mas o seguinte não funciona:

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

Isso me confunde, porque os seguintes métodos que pesquisam em uma coleção parecem bem:

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

O que estou fazendo de errado? Como verifico a associação de um objeto em uma coleção includes?

edit: a pergunta foi originalmente para o lodash versão 2.4.1, atualizada para o lodash 4.0.0

Conrad.Dean
fonte
7
_.containsfoi removido no lodash v4 - em _.includesvez disso, use #
Billy Moon
@BillyMoon woops! sim, você está certo, o lodash v4.0.0 (lançado em 12-01-2016) remove o containsalias.
Atualizo

Respostas:

222

O método includes(anteriormente chamado containse include) compara objetos por referência (ou mais precisamente, com ===). Como os dois literais de objeto do {"b": 2}seu exemplo representam instâncias diferentes , eles não são iguais. Aviso prévio:

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

No entanto, isso funcionará porque há apenas uma instância de {"b": 2}:

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

Por outro lado, os métodos where(descontinuado na v4) e os findmétodos comparam objetos por suas propriedades, para que eles não exijam igualdade de referência. Como alternativa includes, você pode tentar some(também conhecido como any):

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

Complementando a resposta p.s.w.g, aqui estão três outras maneiras de conseguir isso usando lodash 4.17.5, sem usar _.includes() :

Digamos que você queira adicionar um objeto entrya uma matriz de objetos numbers, apenas se entryainda não existir.

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

Se você quiser retornar um Boolean, no primeiro caso, poderá verificar o índice que está sendo retornado:

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