web-dev-qa-db-fra.com

Dans un tableau d'objets, moyen le plus rapide de trouver l'index d'un objet dont les attributs correspondent à une recherche

Je surfe un peu en essayant de trouver un moyen efficace de le faire, mais je ne suis nulle part. J'ai un tableau d'objets qui ressemble à ceci:

array[i].id = some number;
array[i].name = some name;

Ce que je veux faire est de trouver les index des objets où id est égal à, par exemple, un des 0,1,2,3 ou 4 . Je suppose que je pourrais faire quelque chose comme:

var indexes = [];
for(i=0; i<array.length; i++) {
  (array[i].id === 0) ? { indexes[0] = i }
  (array[i].id === 1) ? { indexes[1] = i }
  (array[i].id === 2) ? { indexes[2] = i }
  (array[i].id === 3) ? { indexes[3] = i }
  (array[i].id === 4) ? { indexes[4] = i }
}

Bien que cela fonctionne, il semble être assez coûteux et lent (pour ne pas dire laid), surtout si array.length pourrait être grand. Des idées sur la façon d'améliorer ce un peu? J'ai pensé à utiliser array.indexOf d'une manière ou d'une autre mais je ne vois pas comment forcer la syntaxe. Ce

array.indexOf(this.id === 0);

par exemple, retourne undefined, comme il se doit probablement . Merci d'avance!

118
Petrov

Vous voudrez peut-être utiliser des fonctions d'ordre supérieur telles que "map" . En supposant que vous souhaitiez effectuer une recherche par attribut 'field':

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];

Le moyen le plus simple et le plus simple de rechercher un index d'élément dans un tableau.

Syntaxe ES5: [{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

Syntaxe ES6: [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)

44
Umair Ahmed

La nouvelle méthode Array .filter () fonctionnerait bien pour ceci:

var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery peut aussi le faire avec .grep ()

edit: il est à noter que ces deux fonctions se contentent de se glisser sous le capot, il n’y aura pas de différence de performance notable entre elles et l’utilisation de votre propre fonction de filtre, mais pourquoi réinventer la roue.

26
jbabey
array.forEach(function (elem, i) {  // iterate over all elements of array
    indexes[elem.id] = i;           // take the found id as index for the
});                                 // indexes array and assign i

le résultat est une liste de recherche pour l'identifiant. avec l'identifiant donné, nous obtenons l'index de l'enregistrement.

7
Nina Scholz
var indices = [];
var IDs = [0, 1, 2, 3, 4];

for(var i = 0, len = array.length; i < len; i++) {
    for(var j = 0; j < IDs.length; j++) {
        if(array[i].id == ID) indices.Push(i);
    }
}
6

Comme il n'y a pas de réponse en utilisant un tableau régulier find:

var one = {id: 1, name: 'one'};
var two = {id: 2, name:'two'}
var arr = [one, two] 

var found = arr.find((a) => a.id === 2)

found === two // true

arr.indexOf(found) // 1
5
enapupe

Si vous vous souciez de la performance, n'allez pas avec find ou filter ou map ou l'une des méthodes décrites ci-dessus.

Voici un exemple démontrant la méthode la plus rapide. ICI est le lien vers le test actuel

Bloc d'installation

var items = []

for(var i = 0; i < 1000; i++) {
    items.Push({id: i + 1})
}

var find = 523

Méthode la plus rapide

var index = -1
for(var i = 0; i < items.length; i++) {
    if(items[i].id === find) {
        index = i;
        break;
    }
}

Méthodes plus lentes

items.findIndex(item => item.id === find)

Méthode la plus lente

items.map(item => item.id).indexOf(find);
3
PirateApp

Une nouvelle façon d'utiliser ES6

let picked_element = array.filter(element => element.id === 0);
3
Silve2611

Pour résumer toute l'excellente réponse ci-dessus et en plus de ma réponse concernant trouver tous les index sont issus de certains commentaires.

  1. Pour renvoyer l'index de la première occurrence.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }];
const idYourAreLookingFor = 2;

//ES5 
//Output: 1
array.map(function (x) { return x.id; }).indexOf(idYourAreLookingFor);

//ES6 
//Output: 1
array.findIndex(obj => obj.id === idYourAreLookingFor);

  1. Pour renvoyer le tableau d'index de toutes les occurrences, utilisez la réduction.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }]
const idYourAreLookingFor = 2;

//ES5
//Output: [1, 4]
array.reduce(function (acc, obj, i) {
  if (obj.id === idYourAreLookingFor)
    acc.Push(i);
  return acc;
}, []);

//ES6
//Output: [1, 4]
array.reduce((acc, obj, i) => (obj.id === idYourAreLookingFor) ? acc.concat(i) : acc, [])

2
trungk18

Adapter la réponse de Tejs pour mongoDB et Robomongo, j'ai changé 

matchingIndices.Push(j);

à

matchingIndices.Push(NumberInt(j+1));
2
user2584621

Il me semble que vous pourriez créer un simple itérateur avec un rappel pour les tests. Ainsi:

function findElements(array, predicate)
{
    var matchingIndices = [];

    for(var j = 0; j < array.length; j++)
    {
        if(predicate(array[j]))
           matchingIndices.Push(j);
    }

    return matchingIndices;
}

Ensuite, vous pouvez invoquer comme suit:

var someArray = [
     { id: 1, text: "Hello" },
     { id: 2, text: "World" },
     { id: 3, text: "Sup" },
     { id: 4, text: "Dawg" }
  ];

var matchingIndices = findElements(someArray, function(item)
   {
        return item.id % 2 == 0;
   });

// Should have an array of [1, 3] as the indexes that matched
2
Tejs

Utilisation de la fonction ES6 map:

let idToFind = 3;
let index = someArray.map(obj => obj.id).indexOf(idToFind);
2
JoeTidee
var test = [
  {id:1, test: 1},
  {id:2, test: 2},
  {id:2, test: 2}
];

var result = test.findIndex(findIndex, '2');

console.log(result);

function findIndex(object) {
  return object.id == this;
}

retournera l'index 1 (fonctionne uniquement dans ES 2016)

0
eXtreme

J'aime cette méthode car il est facile de comparer toute valeur de l'objet, quelle que soit la profondeur d'imbrication.

 while(i<myArray.length && myArray[i].data.value!==value){
  i++; 
}
// i now hows the index value for the match. 
 console.log("Index ->",i );
0
Daniel Lefebvre

Comme je ne peux pas encore commenter, je veux montrer la solution que j'ai utilisée, basée sur la méthode publiée par Umair Ahmed, mais lorsque vous souhaitez rechercher une clé au lieu d'une valeur:

[{"a":true}, {"f":true}, {"g":false}]
.findIndex(function(element){return Object.keys(element)[0] == "g"});

Je comprends que cela ne répond pas à la question élargie, mais que le titre ne précise pas ce que l’on voulait de chaque objet. Je souhaite donc partager cela humblement pour éviter des maux de tête à d’autres, alors que je ne le désestime pas. solution la plus rapide.

0
Xander N

J'ai créé un petit utilitaire appelé super-array où vous pouvez accéder aux éléments d'un tableau à l'aide d'un identifiant unique de complexité O(1). Exemple:

const SuperArray = require('super-array');

const myArray = new SuperArray([
  {id: 'ab1', name: 'John'},
  {id: 'ab2', name: 'Peter'},
]);

console.log(myArray.get('ab1')); // {id: 'ab1', name: 'John'}
console.log(myArray.get('ab2')); // {id: 'ab2', name: 'Peter'}
0
patotoma