web-dev-qa-db-fra.com

Rechercher un objet par identifiant dans un tableau d'objets JavaScript

J'ai un tableau:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]

Je suis incapable de changer la structure du tableau. On me transmet un identifiant de 45 et je souhaite obtenir 'bar' pour cet objet dans le tableau 

Comment puis-je faire cela en JavaScript ou en utilisant jQuery?

1246
thugsb

Utilisez la méthode find():

myArray.find(x => x.id === '45').foo;

De MDN :

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


Si vous voulez plutôt trouver son index, utilisez findIndex():

myArray.findIndex(x => x.id === '45');

De MDN :

La méthode findIndex() renvoie l'index du premier élément du tableau qui satisfait à la fonction de test fournie. Sinon, -1 est renvoyé.


Si vous voulez obtenir un tableau d'éléments correspondants, utilisez plutôt la méthode filter() :

myArray.filter(x => x.id === '45');

Cela retournera un tableau d'objets. Si vous voulez obtenir un tableau de propriétés foo, vous pouvez le faire avec la méthode map() :

myArray.filter(x => x.id === '45').map(x => x.foo);

Remarque secondaire: les méthodes telles que find() ou filter() et 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 transcrire votre code avec Babel (avec le polyfill ).

677
Michał Perłakowski

Comme vous utilisez déjà jQuery, vous pouvez utiliser la fonction grep qui est destinée à la recherche dans un tableau:

var result = $.grep(myArray, function(e){ return e.id == id; });

Le résultat est un tableau avec les éléments trouvés. Si vous savez que l'objet est toujours là et qu'il ne se produit qu'une fois, vous pouvez simplement utiliser result[0].foo pour obtenir la valeur. Sinon, vous devriez vérifier la longueur du tableau résultant. Exemple:

if (result.length == 0) {
  // not found
} else if (result.length == 1) {
  // access the foo property using result[0].foo
} else {
  // multiple items found
}
1430
Guffa

Une autre solution consiste à créer un objet de recherche:

var lookup = {};
for (var i = 0, len = array.length; i < len; i++) {
    lookup[array[i].id] = array[i];
}

... now you can use lookup[id]...

Ceci est particulièrement intéressant si vous devez effectuer de nombreuses recherches.

Cela n'aura pas besoin de beaucoup plus de mémoire car les identifiants et les objets seront partagés.

347
Aaron Digulla

ECMAScript 2015 fournit la méthode find () sur les tableaux: 

var myArray = [
 {id:1, name:"bob"},
 {id:2, name:"dan"},
 {id:3, name:"barb"},
]

// grab the Array item which matchs the id "2"
var item = myArray.find(item => item.id === 2);

// print
console.log(item.name);

Cela fonctionne sans bibliothèques externes. Mais si vous voulez les anciens navigateurs , vous voudrez peut-être inclure this polyfill .

158
Rúnar Berg

Underscore.js a une méthode intéressante pour cela:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
obj = _.find(myArray, function(obj) { return obj.id == '45' })
140
GijsjanB

Je pense que le moyen le plus simple serait le suivant, mais cela ne fonctionnera pas sur Internet Explorer 8 (ou antérieur):

var result = myArray.filter(function(v) {
    return v.id === '45'; // Filter out the appropriate one
})[0].foo; // Get result and access the foo property
123
pimvdb

Essayez ce qui suit

function findById(source, id) {
  for (var i = 0; i < source.length; i++) {
    if (source[i].id === id) {
      return source[i];
    }
  }
  throw "Couldn't find object with id: " + id;
}
65
JaredPar
myArray.filter(function(a){ return a.id == some_id_you_want })[0]
42
Danilo Colasso

Une version générique et plus flexible de la fonction findById ci-dessus:

// array = [{key:value},{key:value}]
function objectFindByKey(array, key, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return array[i];
        }
    }
    return null;
}

var array = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var result_obj = objectFindByKey(array, 'id', '45');
30
will Farrell

Vous pouvez l'obtenir facilement en utilisant la fonction map () :

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var found = $.map(myArray, function(val) {
    return val.id == 45 ? val.foo : null;
});

//found[0] == "bar";

Exemple de travail: http://jsfiddle.net/hunter/Pxaua/

14
hunter

Vous pouvez utiliser des filtres,

  function getById(id, myArray) {
    return myArray.filter(function(obj) {
      if(obj.id == id) {
        return obj 
      }
    })[0]
  }

get_my_obj = getById(73, myArray);
13
Joe Lewis

Bien qu'il y ait beaucoup de réponses correctes ici, beaucoup d'entre elles n'abordent pas le fait qu'il s'agit d'une opération inutilement coûteuse si elle est effectuée plus d'une fois. Dans des cas extrêmes, cela pourrait être la cause de problèmes de performances réels.

Dans le monde réel, si vous traitez un grand nombre d'éléments et que les performances sont une préoccupation, il est beaucoup plus rapide de créer initialement une recherche:

var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});

vous pouvez alors obtenir des objets à temps fixe comme ceci: 

var bar = o[id];

Vous pouvez également envisager d’utiliser une carte au lieu d’un objet comme recherche: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map

10
Tom

Utiliser natif Array.reduce

var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
var id = 73;
var found = array.reduce(function(a, b){
    return (a.id==id && a) || (b.id == id && b)
});

retourne l'élément object si trouvé, sinon false

10
laggingreflex

Voici comment je m'y prendrais en JavaScript pur, de la manière la plus minimale qui soit, qui fonctionne dans ECMAScript 3 ou une version ultérieure. Il revient dès qu'une correspondance est trouvée.

var getKeyValueById = function(array, key, id) {
    var testArray = array.slice(), test;
    while(test = testArray.pop()) {
        if (test.id === id) {
            return test[key];
        }
    }
    // return undefined if no matching id is found in array
    return;
}

var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
var result = getKeyValueById(myArray, 'foo', '45');

// result is 'bar', obtained from object with id of '45'
6
Dan W

S'appuyant sur la réponse acceptée:

jQuery:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)

Ou CoffeeScript:

foo = $.grep myArray, (e) -> e.id == foo_id
myArray.pop foo
4
mr.musicman

Vous pouvez essayer Sugarjs depuis http://sugarjs.com/ .

Il utilise une méthode très douce sur les tableaux, .find. Vous pouvez donc trouver un élément comme celui-ci:

array.find( {id: 75} );

Vous pouvez également passer un objet avec plus de propriétés pour ajouter une autre "clause-où".

Notez que Sugarjs étend les objets natifs, et certaines personnes considèrent cela comme très mal ...

4
deepflame

Si vous faites cela plusieurs fois, vous pouvez configurer une carte (ES6):

const map = new Map( myArray.map(el => [el.id, el]) );

Ensuite, vous pouvez simplement faire:

map.get(27).foo
4
Jonas Wilms

Utilisez la fonction Array.prototype.filter().

DEMO: https://jsfiddle.net/sumitridhal/r0cz0w5o/4/

JSON

var jsonObj =[
 {
  "name": "Me",
  "info": {
   "age": "15",
   "favColor": "Green",
   "pets": true
  }
 },
 {
  "name": "Alex",
  "info": {
   "age": "16",
   "favColor": "orange",
   "pets": false
  }
 },
{
  "name": "Kyle",
  "info": {
   "age": "15",
   "favColor": "Blue",
   "pets": false
  }
 }
];

FILTRE

var getPerson = function(name){
    return jsonObj.filter(function(obj) {
      return obj.name === name;
    });
}
3
Sumit Ridhal

Itérer sur n'importe quel élément du tableau. Pour chaque article que vous visitez, vérifiez son identifiant. Si c'est une correspondance, retournez-la.

Si vous voulez juste le code:

function getId(array, id) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].id === id) {
            return array[i];
        }
    }
    return null; // Nothing found
}

Et la même chose en utilisant les méthodes Array d'ECMAScript 5:

function getId(array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });

    // Filter returns an array, and we just want the matching item.
    return obj[0];
}
3
Zirak

Vous pouvez le faire même en JavaScript pur en utilisant la fonction "filtre" intégrée pour les tableaux:

Array.prototype.filterObjects = function(key, value) {
    return this.filter(function(x) { return x[key] === value; })
}

Alors maintenant, passez simplement "id" à la place de key et "45" à la place de value, et vous obtiendrez l'objet complet correspondant à un id de 45. Ce serait donc:

myArr.filterObjects("id", "45");
3
kaizer1v

Tant que le navigateur prend en charge ECMA-262 , 5ème édition (décembre 2009), cela devrait fonctionner, presque en une ligne:

var bFound = myArray.some(function (obj) {
    return obj.id === 45;
});
2
aggaton

J'ai vraiment aimé la réponse fournie par Aaron Digulla, mais je devais conserver mon tableau d'objets pour pouvoir le parcourir plus tard. Alors je l'ai modifié pour 

	var indexer = {};
	for (var i = 0; i < array.length; i++) {
	    indexer[array[i].id] = parseInt(i);
	}
	
	//Then you can access object properties in your array using 
	array[indexer[id]].property

2
quincyaft

Cette solution peut également être utile:

Array.prototype.grep = function (key, value) {
    var that = this, ret = [];
    this.forEach(function (elem, index) {
        if (elem[key] === value) {
            ret.Push(that[index]);
        }
    });
    return ret.length < 2 ? ret[0] : ret;
};
var bar = myArray.grep("id","45");

Je l'ai fait comme $.grep et si un objet est découvert, fonction retournera l'objet, plutôt qu'un tableau.

1
soytian

Utilisation:

var retObj ={};
$.each(ArrayOfObjects, function (index, obj) {

        if (obj.id === '5') { // id.toString() if it is int

            retObj = obj;
            return false;
        }
    });
return retObj;

Il devrait retourner un objet par id.

1
volumexxx

Considérez "axesOptions" comme un tableau d'objets dont le format est {: Field_type => 2,: fields => [1,3,4]}

function getFieldOptions(axesOptions,choice){
  var fields=[]
  axesOptions.each(function(item){
    if(item.field_type == choice)
        fields= hashToArray(item.fields)
  });
  return fields;
}
0
ramya

Plus générique et court

function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}

dans votre cas Ex. var element = findFromArray(myArray,'id',45) qui vous donnera l’élément entier.

0
Savan Kaneriya

Le plus court,

var theAnswerObj = _.findWhere(array, {id : 42});
0
Manu

Nous pouvons utiliser les méthodes Jquery $ .each ()/$. Grep () var data= []; $.each(array,function(i){if(n !== 5 && i > 4){data.Push(item)}}

ou 

var data = $.grep(array, function( n, i ) { return ( n !== 5 && i > 4 ); });

utilisez la syntaxe ES6: Array.find, Array.filter, Array.forEach, Array.map

Ou utilisez Lodash https://lodash.com/docs/4.17.10#filter , Underscore https://underscorejs.org/#filter

0
TLbiz

À partir de aggaton's answer , il s'agit d'une fonction qui renvoie l'élément recherché (ou null si introuvable), étant donné la fonction array et une fonction callback qui renvoie une valeur de vérité pour l'élément "correct"

function findElement(array, callback) {
    var elem;
    return array.some(function(e) {
        if (callback(e)) {
            elem = e;
            return true;
        }
    }) ? elem : null;
});

Rappelez-vous simplement que cela ne fonctionne pas nativement sur IE8-, car il ne supporte pas some. Un polyfill peut être fourni, sinon il y a toujours la boucle for classique:

function findElement(array, callback) {
    for (var i = 0; i < array.length; i++)
        if (callback(array[i])) return array[i];
    return null;
});

C'est en fait plus rapide et plus compact. Mais si vous ne voulez pas réinventer la roue, je suggère d'utiliser une bibliothèque d'utilitaires telle que le soulignement ou le lodash.

0
MaxArt