keys - Obtener objeto JavaScript de una matriz de objetos por valor de propiedad
recorrer array de objetos javascript (17)
Esta pregunta ya tiene una respuesta aquí:
Digamos que tengo una matriz de cuatro objetos:
var jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
];
¿Hay alguna forma de obtener el tercer objeto ( {a: 5, b: 6}
) por el valor de la propiedad b
por ejemplo, sin un for...in
loop?
¿Qué hay de usar _.find(collection, [predicate=_.identity], [fromIndex=0])
de lo-dash para obtener el objeto de una matriz de objetos por valor de propiedad del objeto? Podrías hacer algo como esto:
var o = _.find(jsObjects, {''b'': 6});
Argumentos:
collection (Array|Object): The collection to inspect.
[predicate=_.identity] (Function): The function invoked per iteration.
[fromIndex=0] (number): The index to search from.
Devoluciones
(*): Returns the matched element (in your case, {a: 5, b: 6}), else undefined.
En términos de rendimiento, _.find()
es más rápido, ya que solo extrae el primer objeto con la propiedad {''b'': 6}
, por otro lado, si supones que tu matriz contiene varios objetos con un conjunto de propiedades coincidentes (clave: valor ), entonces deberías considerar usar el método _.filter()
. Entonces, en su caso, como su matriz tiene un solo objeto con esta propiedad, usaría _.find()
.
Consulte esta documentación https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values
Ejemplo:
var inventory = [
{name: ''apples'', quantity: 2},
{name: ''bananas'', quantity: 0},
{name: ''cherries'', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === ''cherries'';
}
console.log(inventory.find(findCherries));
// { name: ''cherries'', quantity: 5 }
No sé por qué estás en contra de un bucle for (presumiblemente te refieres a un bucle for, no específicamente para ... en), son rápidos y fáciles de leer. De todos modos, aquí hay algunas opciones.
En bucle:
function getByValue(arr, value) {
for (var i=0, iLen=arr.length; i<iLen; i++) {
if (arr[i].b == value) return arr[i];
}
}
.filtrar
function getByValue2(arr, value) {
var result = arr.filter(function(o){return o.b == value;} );
return result? result[0] : null; // or undefined
}
.para cada
function getByValue3(arr, value) {
var result = [];
arr.forEach(function(o){if (o.b == value) result.push(o);} );
return result? result[0] : null; // or undefined
}
Si, por otro lado, realmente quiso decir para ... en y quiere encontrar un objeto con alguna propiedad con un valor de 6, entonces debe usar para ... en menos que pase los nombres para verificar. p.ej
function getByValue4(arr, value) {
var o;
for (var i=0, iLen=arr.length; i<iLen; i++) {
o = arr[i];
for (var p in o) {
if (o.hasOwnProperty(p) && o[p] == value) {
return o;
}
}
}
}
Para obtener el primer objeto de la matriz de objetos por un valor de propiedad específico:
function getObjectFromObjectsArrayByPropertyValue(objectsArray, propertyName, propertyValue) {
return objectsArray.find(function (objectsArrayElement) {
return objectsArrayElement[propertyName] == propertyValue;
});
}
function findObject () {
var arrayOfObjectsString = document.getElementById("arrayOfObjects").value,
arrayOfObjects,
propertyName = document.getElementById("propertyName").value,
propertyValue = document.getElementById("propertyValue").value,
preview = document.getElementById("preview"),
searchingObject;
arrayOfObjects = JSON.parse(arrayOfObjectsString);
console.debug(arrayOfObjects);
if(arrayOfObjects && propertyName && propertyValue) {
searchingObject = getObjectFromObjectsArrayByPropertyValue(arrayOfObjects, propertyName, propertyValue);
if(searchingObject) {
preview.innerHTML = JSON.stringify(searchingObject, false, 2);
} else {
preview.innerHTML = "there is no object with property " + propertyName + " = " + propertyValue + " in your array of objects";
}
}
}
pre {
padding: 5px;
border-radius: 4px;
background: #f3f2f2;
}
textarea, button {
width: 100%
}
<fieldset>
<legend>Input Data:</legend>
<label>Put here your array of objects</label>
<textarea rows="7" id="arrayOfObjects">
[
{"a": 1, "b": 2},
{"a": 3, "b": 4},
{"a": 5, "b": 6},
{"a": 7, "b": 8, "c": 157}
]
</textarea>
<hr>
<label>property name: </label> <input type="text" id="propertyName" value="b"/>
<label>property value: </label> <input type="text" id="propertyValue" value=6 />
</fieldset>
<hr>
<button onclick="findObject()">find object in array!</button>
<hr>
<fieldset>
<legend>Searching Result:</legend>
<pre id="preview">click find</pre>
</fieldset>
Parece que en la propuesta de ECMAScript 6 están los métodos Array
find()
y findIndex()
. MDN también ofrece polyfills que puede incluir para obtener la funcionalidad de estos en todos los navegadores.
find()
:
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].findIndex(isPrime) ); // -1, not found
console.log( [4, 6, 7, 12].findIndex(isPrime) ); // 2
Pruebe el método de filtro de array of objects
para filtrar la array of objects
con property
.
var jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
];
utilizando el método de filtro de matriz:
var filterObj = jsObjects.filter(function(e) {
return e.b == 6;
});
utilizando for in loop:
for (var i in jsObjects) {
if (jsObjects[i].b == 6) {
console.log(jsObjects[i]); // {a: 5, b: 6}
}
}
Fiddle de trabajo: https://jsfiddle.net/uq9n9g77/
Puede usarlo con la función de flecha como se muestra a continuación:
var demoArray = [
{name: ''apples'', quantity: 2},
{name: ''bananas'', quantity: 0},
{name: ''cherries'', quantity: 5}
];
var result = demoArray.filter( obj => obj.name === ''apples'')[0];
console.log(result);
// {name: ''apples'', quantity: 2}
Si comprendo correctamente, ¿desea buscar el objeto en la matriz cuya propiedad b
es 6
?
var found;
jsObjects.some(function (obj) {
if (obj.b === 6) {
found = obj;
return true;
}
});
O si estabas usando guiones bajos:
var found = _.select(jsObjects, function (obj) {
return obj.b === 6;
});
Si está buscando un solo resultado, en lugar de una matriz, ¿puedo sugerirle que reduzca?
Aquí hay una solución en un simple ''ole javascript que devuelve un objeto coincidente si existe, o nulo si no es así.
var result = arr.reduce(function(prev, curr) { return (curr.b === 6) ? curr : prev; }, null);
Simplemente mejoré la parte más rápida / mejor de esta respuesta para que sea más reutilizable / claro:
function getElByPropVal(arr, prop, val){
for (var i = 0, length = arr.length; i < length; i++) {
if (arr[i][prop] == val){
return arr[i];
}
}
}
Usando find with bind para pasar valores clave específicos a una función de devolución de llamada.
function byValue(o) {
return o.a === this.a && o.b === this.b;
};
var result = jsObjects.find(byValue.bind({ a: 5, b: 6 }));
Utilizando underscore.js:
var foundObject = _.findWhere(jsObjects, {b: 6});
Filter
matriz de objetos, cuya propiedad coincide con el valor, devuelve la matriz:
var result = jsObjects.filter(obj => {
return obj.b === 6
})
Consulte los documentos MDN en Array.prototype.filter ()
const jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
]
let result = jsObjects.filter(obj => {
return obj.b === 6
})
console.log(result)
Find
el valor del primer elemento / objeto en la matriz, de lo contrario se devuelve undefined
.
var result = jsObjects.find(obj => {
return obj.b === 6
})
Consulte los documentos MDN en Array.prototype.find ()
const jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
]
let result = jsObjects.find(obj => {
return obj.b === 6
})
console.log(result)
Está bien, hay algunas formas de hacerlo, pero comencemos con el método más simple y el más reciente para hacer esto, esta función se llama find()
.
Solo tenga cuidado cuando use find
to, ya que incluso IE11 no lo admite, por lo que necesita ser transpilado ...
así que tienes este objeto como dijiste:
var jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8}
];
y puedes escribir una función y obtenerla así:
function filterValue(obj, key, value) {
return obj.find(function(v){ return v[key] === value});
}
y usa la función así:
filterValue(jsObjects, "b", 6); //{a: 5, b: 6}
También en ES6 para versiones incluso más cortas:
const filterValue = (obj, key, value)=> obj.find(v => v[key] === value);
Este método solo devuelve el primer valor que coincida con ... Para obtener mejores resultados y compatibilidad con el navegador, puede usar el filter
:
const filterValue = (obj, key, value)=> obj.filter(v => v[key] === value);
y devolveremos [{a: 5, b: 6}]
...
Este método devolverá una matriz en su lugar ...
Usted simplemente usa para bucle también, crea una función como esta:
function filteredArray(arr, key, value) {
const newArray = [];
for(i=0, l=arr.length; i<l; i++) {
if(arr[i][key] === value) {
newArray.push(arr[i]);
}
}
return newArray;
}
y llámalo así:
filteredArray(jsObjects, "b", 6); //[{a: 5, b: 6}]
jsObjects.find(x => x.b === 6)
Desde MDN:
El método
find()
devuelve un valor en la matriz, si un elemento de la matriz satisface la función de prueba provista. De lo contrario se devuelveundefined
.
Nota al margen: los métodos como find()
y las funciones de flecha no son compatibles con los navegadores más antiguos (como IE), por lo que si desea admitir estos navegadores, debe transpilar su código utilizando Babel .
var jsObjects = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8}];
para acceder al tercer objeto, use: jsObjects[2];
para acceder al valor del tercer objeto b, use: jsObjects[2].b;
var result = jsObjects.filter(x=> x.b === 6);
será mejor, usando el retorno en el filtro a veces no puede obtener un resultado (no sé por qué)