web-dev-qa-db-fra.com

Obtenir un objet JavaScript à partir d'un tableau d'objets par la valeur de la propriété

Disons que j'ai un tableau de quatre objets:

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];

Est-il possible d'obtenir le troisième objet ({a: 5, b: 6}) à l'aide de la valeur de la propriété b, par exemple sans boucle for...in?

560
user765368

Filter tableau d'objets, dont la propriété correspond à valeur, retourne tableau:

var result = jsObjects.filter(obj => {
  return obj.b === 6
})

Voir le Docs MDN sur 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 la valeur du premier élément/objet du tableau, sinon undefined est renvoyé.

var result = jsObjects.find(obj => {
  return obj.b === 6
})

Voir le Docs MDN sur 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)

812
elclanrs
jsObjects.find(x => x.b === 6)

De MDN:

La méthode find() renvoie une valeur dans le tableau, si un élément du tableau satisfait à la fonction de test fournie. Sinon, undefined est renvoyé.


Remarque secondaire: les méthodes telles que find() et les fonctions de flèche ne sont pas prises en charge par les anciens navigateurs (comme IE). Par conséquent, si vous souhaitez prendre en charge ces navigateurs, vous devez transpiler votre code avec Babel .

221
Michał Perłakowski

Je ne sais pas pourquoi vous êtes contre une boucle for (vraisemblablement vous vouliez dire une boucle for, pas spécifiquement pour..in), elles sont rapides et faciles à lire. Quoi qu'il en soit, voici quelques options.

Pour boucle:

function getByValue(arr, value) {

  for (var i=0, iLen=arr.length; i<iLen; i++) {

    if (arr[i].b == value) return arr[i];
  }
}

.filtre

function getByValue2(arr, value) {

  var result  = arr.filter(function(o){return o.b == value;} );

  return result? result[0] : null; // or undefined

}

.pour chaque

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, par contre, vous vouliez vraiment dire for..in et souhaitez rechercher un objet avec une propriété de valeur 6, vous devez utiliser for..in sauf si vous passez les noms à vérifier. par exemple.

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;
      }
    }
  }
}
136
RobG

Try Array filter méthode pour filtrer le array of objects avec property.

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];

en utilisant la méthode de filtrage de tableau:

var filterObj = jsObjects.filter(function(e) {
  return e.b == 6;
});

utilisant pour la boucle d'entrée:

for (var i in jsObjects) {
  if (jsObjects[i].b == 6) {
    console.log(jsObjects[i]); // {a: 5, b: 6}
  }
}

Le violon en marche:https://jsfiddle.net/uq9n9g77/

31
Rohit Jindal

Utilisation de underscore.js:

var foundObject = _.findWhere(jsObjects, {b: 6});
19
maia

Il semble que dans la proposition ECMAScript 6, il existe les méthodes Array, find() et findIndex(). MDN propose également des polyfill que vous pouvez inclure pour obtenir la fonctionnalité de ceux-ci sur tous les navigateurs.

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

findIndex() :

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
17
Amir

Si je comprends bien, vous voulez trouver l’objet dans le tableau dont la propriété b est 6?

var found;
jsObjects.some(function (obj) {
  if (obj.b === 6) {
    found = obj;
    return true;
  }
});

Ou si vous utilisiez un trait de soulignement:

var found = _.select(jsObjects, function (obj) {
  return obj.b === 6;
});
14
nickf

OK, il y a peu de façons de le faire, mais commençons par la plus simple et la plus récente des méthodes, cette fonction s'appelle find().

Faites attention quand vous utilisez find car même IE11 ne le supporte pas, il doit donc être transpilé ...

alors vous avez cet objet comme vous l'avez dit:

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];

et vous pouvez écrire une fonction et l'obtenir comme ceci:

function filterValue(obj, key, value) {
  return obj.find(function(v){ return v[key] === value});
}

et utilisez la fonction comme ceci:

filterValue(jsObjects, "b", 6); //{a: 5, b: 6}

Aussi dans ES6 pour même la version abrégée:

const filterValue = (obj, key, value)=> obj.find(v => v[key] === value);

Cette méthode ne renvoie que la première valeur qui correspond ... Pour une meilleure prise en charge des résultats et du navigateur, vous pouvez utiliser filter:

const filterValue = (obj, key, value)=> obj.filter(v => v[key] === value);

et nous retournerons [{a: 5, b: 6}]...

Cette méthode retournera un tableau à la place ...

Vous utilisez aussi très simplement boucle, créez une fonction comme celle-ci:

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

et appelez ça comme ça:

filteredArray(jsObjects, "b", 6); //[{a: 5, b: 6}]
13
Alireza

Si vous recherchez un seul résultat plutôt qu'un tableau, puis-je suggérer de réduire? 

Voici une solution en clair 'ole javascript qui retourne un objet correspondant s'il en existe un ou null si ce n'est pas le cas.

var result = arr.reduce(function(prev, curr) { return (curr.b === 6) ? curr : prev; }, null);
12
Sam Dushay

Pourquoi ne pas utiliser _.find(collection, [predicate=_.identity], [fromIndex=0]) de lo-dash pour obtenir un objet à partir d’un tableau d’objets par valeur de propriété d’objet. Vous pouvez faire quelque chose comme ça: 

var o = _.find(jsObjects, {'b': 6});

Arguments: 

collection (Array|Object): The collection to inspect.
[predicate=_.identity] (Function): The function invoked per iteration.
[fromIndex=0] (number): The index to search from.

Résultats

(*): Returns the matched element (in your case, {a: 5, b: 6}), else undefined.

En termes de performances, _.find() est plus rapide car il extrait uniquement le premier objet avec la propriété {'b': 6}. Par contre, si supposons que votre tableau contienne plusieurs objets avec un ensemble de propriétés correspondant (clé: valeur), vous devriez envisager d'utiliser la méthode _.filter(). Donc dans votre cas, comme votre tableau a un seul objet avec cette propriété, je voudrais utiliser _.find()

9
Simple-Solution

Vous pouvez l'utiliser avec la fonction de flèche comme ci-dessous:

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}
6
Shobhit Sharma

Voir cette documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values ​​
Exemple : 

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 }
4
asrulsibaoel

Juste amélioré la partie la plus rapide/meilleure de cette réponse pour être plus réutilisable/plus clair:

function getElByPropVal(arr, prop, val){
    for (var i = 0, length = arr.length; i < length; i++) {
        if (arr[i][prop] == val){
            return arr[i];
        }
    }
}
3
Andrew

Pour obtenir le premier objet d'un tableau d'objets avec une valeur de propriété spécifique:

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>

1
misher
var result = jsObjects.filter(x=> x.b === 6);

sera mieux, en utilisant le filtre de retour dans parfois vous ne pouvez pas obtenir de résultat

0
Died

Utilisez find with bind pour transmettre des valeurs de clé spécifiques à une fonction de rappel. 

   function byValue(o) { 
       return o.a === this.a && o.b === this.b; 
   };   

   var result = jsObjects.find(byValue.bind({ a: 5, b: 6 }));
0
Serjuice