¿Cómo uso el método de inclusión en lodash para verificar si un objeto está en la colección?

146

lodash me permite verificar la membresía de los tipos de datos básicos con includes:

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

Pero lo siguiente no funciona:

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

Esto me confunde porque los siguientes métodos que buscan en una colección parecen funcionar bien:

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

¿Qué estoy haciendo mal? ¿Cómo verifico la pertenencia de un objeto en una colección includes?

editar: la pregunta era originalmente para lodash versión 2.4.1, actualizada para lodash 4.0.0

Conrad.Dean
fuente
77
_.containsha sido eliminado en lodash v4 - usar _.includesen su lugar
Billy Moon
@BillyMoon woops! sí, tienes razón, lodash v4.0.0 (lanzado el 12/01/2016) elimina el containsalias. Actualizaré esto
Conrad

Respuestas:

222

El método includes(anteriormente llamado containsy include) compara objetos por referencia (o más precisamente, con ===). Debido a que los dos literales de objeto {"b": 2}en su ejemplo representan instancias diferentes , no son iguales. Aviso:

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

Sin embargo, esto funcionará porque solo hay una instancia de {"b": 2}:

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

Por otro lado, el where(en desuso en v4) y los findmétodos comparan objetos por sus propiedades, por lo que no requieren igualdad de referencia. Como alternativa a includes, es posible que desee probar some(también alias como any):

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

Complementando la respuesta con p.s.w.g, aquí hay otras tres formas de lograr esto usando lodash 4.17.5, sin usar _.includes() :

Supongamos que desea agregar un objeto entrya una matriz de objetos numbers, solo si entryaún no existe.

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 desea devolver a Boolean, en el primer caso, puede verificar el índice que se devuelve:

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