Cómo determinar si una matriz de JavaScript contiene un objeto con un atributo que es igual a un valor dado

8 minutos de lectura

Avatar de usuario de David Lozzi
David Lozzi

tengo una matriz como

vendors = [{
    Name: 'Magenic',
    ID: 'ABC'
  },
  {
    Name: 'Microsoft',
    ID: 'DEF'
  } // and so on...
];

¿Cómo verifico esta matriz para ver si existe “Magenic”? No quiero hacer un bucle, a menos que tenga que hacerlo. Estoy trabajando con potencialmente un par de miles de registros.

  • La solución @CAFxX es mejor, sería increíble si actualiza la solución seleccionada.

    – eMarine

    1 de diciembre de 2015 a las 10:21

  • De acuerdo, no lo había visto antes!

    – David Lozzi

    5 de agosto de 2016 a las 13:48

  • Puede simplificar esto ahora aún más mediante el uso de funciones de flecha. Todos los navegadores modernos admiten esto y se ve mejor.

    –Piotr Kula

    21 de marzo de 2017 a las 14:04

  • @eMarine: la pregunta OP menciona específicamente el rendimiento como una preocupación principal. Por lo tanto usando filter o some, si bien es bonito, no es tan bueno como usar un bucle explícito. (Exigen un impacto en el rendimiento debido a que tienen que ejecutar la lambda para cada elemento de la matriz).

    – logidelico

    29/11/2018 a las 15:00

  • 420 no puede votar pero esta pregunta muestra un esfuerzo de investigación y es útil y clara

    – Jeannie

    21 mayo 2019 a las 21:18

Avatar de usuario de CAFxX
CAFxX

No hay necesidad de reinventar el rueda loop, al menos no explícitamente (usando funciones de flecha, solo navegadores modernos):

if (vendors.filter(e => e.Name === 'Magenic').length > 0) {
  /* vendors contains the element we're looking for */
}

o, mejor todavíausar alguno ya que permite que el navegador se detenga tan pronto como se encuentre un elemento que coincida, por lo que será más rápido:

if (vendors.some(e => e.Name === 'Magenic')) {
  /* vendors contains the element we're looking for */
}

o el equivalente (en este caso) encontrar:

if (vendors.find(e => e.Name === 'Magenic')) {
  /* same result as above, but a different function return type */
}

E incluso puedes obtener la posición de ese elemento usando buscarÍndice:

const i = vendors.findIndex(e => e.Name === 'Magenic');
if (i > -1) {
  /* vendors contains the element we're looking for, at index "i" */
}

Y si necesita compatibilidad con navegadores pésimos, su mejor opción es:

if (vendors.filter(function(e) { return e.Name === 'Magenic'; }).length > 0) {
  /* vendors contains the element we're looking for */
}

  • @CAFxX ¿Cómo obtendrías el índice cuando lo encuentras? ¿Es esto una posibilidad o funcionaría mejor un bucle para obtener el índice?

    – Echtniet

    03/04/2018 a las 20:44

  • @Echtniet si necesita el índice, entoncessellers.findIndex le dará el índice del primer elemento coincidente. Si, en cambio, necesita el valor, entoncessellers.find le dará el primer elemento coincidente, o vendors.filter le dará todos los elementos coincidentes. Es posible que desee consultar desarrollador.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – CAFxX

    04/04/2018 a las 22:05


  • Por que es some mejor todavía ?

    – 7hibault

    19 de abril de 2019 a las 16:29

  • @7hibault porque some puede cortocircuitar una vez un objeto con name === "Magenic" es encontrado. Con filterverificará cada elemento hasta el final de la matriz y creará una nueva matriz de elementos que coincida con la condición, luego verifique la length

    – adiga

    14 de mayo de 2019 a las 14:03

  • Muchos comentarios sobre .some. Es 2019, usa .some y use Polyfills para admitir navegadores pésimos y seguir adelante con su vida… polyfill.io/v3/url-builder. Lo único que puedo ver es que si no puede admitir funciones de flecha, entonces es tan simple como el Polyfill que mencioné y: arr.some(function(i) { return i.Name === "Magenic" })

    – maxshuty

    24 de diciembre de 2019 a las 12:37

Avatar de usuario de Alex Turpin
Alex Turpin

edición 2018: Esta respuesta es de 2011, antes de que los navegadores tuvieran métodos de filtrado de matrices y funciones de flecha ampliamente compatibles. Eche un vistazo a la respuesta de CAFxX.

No existe una forma “mágica” de buscar algo en una matriz sin un bucle. Incluso si usa alguna función, la función misma usará un bucle. Lo que puede hacer es salir del bucle tan pronto como encuentre lo que está buscando para minimizar el tiempo de cómputo.

var found = false;
for(var i = 0; i < vendors.length; i++) {
    if (vendors[i].Name == 'Magenic') {
        found = true;
        break;
    }
}

  • Ningún problema. Tenga en cuenta que la solución de Keith también es muy viable y le evita bucles.

    – Alex Turpin

    21 de noviembre de 2011 a las 19:41

  • No necesita una bandera si todo lo que necesita saber es si “algo” está o no, simplemente puede verificar el valor del índice de escaneo con el tamaño de la matriz. Para que esto funcione, el índice var debe declararse antes de la instrucción for, por supuesto.

    – Alex

    29/10/2014 a las 21:05

  • Estas opciones parecen funcionar ahora: vendedores.forEach, vendedores.filtro, vendedores.reducir

    – David Lozzi

    5 de agosto de 2016 a las 13:45

  • ¿Qué pasa con JSON.stringify (proveedores). indexOf (‘Magenic’)! == -1

    – Último suspiro

    14 de marzo de 2019 a las 12:23

  • @LastBreath que podría resultar en un falso positivo con bastante facilidad si 'Magenic' está en otro lugar del objeto

    – Alex Turpin

    15 de marzo de 2019 a las 16:22

avatar de usuario de boxtrain
caja de tren

No es necesario un bucle. Hay tres métodos que vienen a la mente:

matriz.prototipo.algunos()

Esta es la respuesta más exacta para su pregunta, es decir, “verificar si existe algo”, lo que implica un resultado bool. Esto será verdadero si hay algún objeto ‘Magenic’, falso de lo contrario:

let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )

matriz.prototipo.filtro()

Esto devolverá una matriz de todos los objetos ‘Magenic’, incluso si solo hay uno (devolverá una matriz de un elemento):

let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )

Si intenta forzar esto a un booleano, no funcionará, ya que una matriz vacía (sin objetos ‘Magenic’) sigue siendo verdadera. Así que solo usa magenicVendors.length en tu condicional.

Array.prototype.find()

Esto devolverá el primer objeto ‘Magenic’ (o undefined si no hay ninguno):

let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );

Esto obliga a un bien booleano (cualquier objeto es veraz, undefined es falso).


Nota: estoy usando proveedor[“Name”] en lugar de proveedor. Nombre debido a la extraña carcasa de los nombres de propiedad.

Nota 2: No hay ninguna razón para usar igualdad flexible (==) en lugar de igualdad estricta (===) al verificar el nombre.

  • Es útil señalar que debajo del capó, todos estos están en bucle. Estos también son más lentos desde el punto de vista computacional que simplemente para realizar bucles y realizar operaciones.

    – La tortuga fiestera

    18/01/2017 a las 19:31

  • También puede ir a compartir ese amor aquí: stackoverflow.com/questions/21748670/… para que más personas como yo no naveguen a esa página antigua y hagan suposiciones.

    – La tortuga fiestera

    19 de enero de 2017 a las 15:55


  • @ThePartyTurtle: ¡Cierto! Aunque las horas de desarrollo suelen ser más caras en comparación con las horas de CPU de los usuarios (y menos código suele ser bueno).

    – Herbert Van-Vliet

    14/09/2022 a las 13:37

Avatar de usuario de TeaCoder
Codificador de té

La respuesta aceptada aún funciona, pero ahora tenemos métodos nativos de ECMAScript 6 [Array.find][1] y [Array.some][2] para lograr el mismo efecto.

matriz.algunos

Usar some Si solo desea determinar si existe un elemento, es decir, necesita un true/false determinación.

Citando a MDN:

El método some() prueba si al menos un elemento de la matriz pasa la prueba implementada por la función proporcionada. Devuelve verdadero si, en la matriz, encuentra un elemento para el cual la función proporcionada devuelve verdadero; de lo contrario, devuelve falso. No modifica la matriz.

matriz.buscar

Use buscar si desea obtener el objeto coincidente de la matriz; de lo contrario, devuelve undefined.

Citando a MDN:

El método find() devuelve el valor del primer elemento de la matriz proporcionada que satisface la función de prueba proporcionada. Si ningún valor satisface la función de prueba, se devuelve undefined.

var arr = [
  {
    id: 21,
    label: 'Banana',
  },
  {
    id: 22,
    label: 'Apple',
  }
]

/* note : data is the actual object that matched search criteria 
  or undefined if nothing matched */

var data = arr.find(function(ele) {
    return ele.id === 21;
});

if (data) {
    console.log('found');
    console.log(data); // This is entire object i.e. `item` not boolean
}


/* note : doesExist is a boolean thats true or false depending on of whether the data was found or not */
var doesExist = arr.some(function(ele) {
    return ele.id === 21;
});


Mira mi enlace jsfiddle Hay un polyfill para IE proporcionado por mozilla

Esta es la forma en que lo haría

const found = vendors.some(item => item.Name === 'Magenic');

array.some() El método comprueba si hay al menos un valor en una matriz que coincida con los criterios y devuelve un valor booleano. De aquí en adelante puedes ir con:

if (found) {
// do something
} else {
// do something else
}

Avatar de usuario de Keith.Abramo
Keith Abramo

A menos que quieras reestructurarlo así:

vendors = {
    Magenic: {
      Name: 'Magenic',
      ID: 'ABC'
     },
    Microsoft: {
      Name: 'Microsoft',
      ID: 'DEF'
    } and so on... 
};

a lo que puedes hacer if(vendors.Magnetic)

Tendrás que hacer un bucle

Avatar de usuario de Peter Mortensen
Pedro Mortensen

Una matriz de JavaScript tiene dos métodos, el some y every métodos que devuelven un valor booleano y pueden ayudarlo a lograrlo.

Creo some sería más apropiado para lo que pretende lograr.

vendors.some(vendor => vendor['Name'] !== 'Magenic')

Algunos validan que cualquiera de los objetos en la matriz satisfaga la condición dada.

vendors.every(vendor => vendor['Name'] !== 'Magenic')

cada valida que todos los objetos en la matriz satisfagan la condición dada.

  • @ThanwaCh. – ¡Debería devolver falso! En tu caso necesitas usar array.some ¡método!

    – Yuriy Anisimov

    22 de julio de 2020 a las 22:57

¿Ha sido útil esta solución?