méthode indexOf dans un tableau d'objets?

Quelle est la meilleure méthode pour obtenir l'index d'un tableau contenant des objets?

Imaginez ce scénario:

var hello = {
    hello: 'world',
    foo: 'bar'
};
var qaz = {
    hello: 'stevie',
    foo: 'baz'
}

var myArray = [];
myArray.push(hello,qaz);

Maintenant, je voudrais avoir l' indexOf l'objet qui hello la propriété est 'stevie', qui, dans cet exemple, serait 1.

Je suis assez débutant avec JavaScript et je ne sais pas s'il existe une méthode simple ou si je devrais construire ma propre fonction pour le faire.

376
demandé sur Armin 2011-12-29 16:59:01

27 réponses

Je pense que vous pouvez le résoudre en une seule ligne en utilisant la fonction map :

pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie');
768
répondu Pablo Francisco Pérez Hidalgo 2018-02-01 13:40:44

Tableau.prototype.findIndex est pris en charge dans tous les navigateurs autres que IE (non-edge). Mais le polyfill fourni est agréable.

var indexOfStevie = myArray.findIndex(i => i.hello === "stevie");

La solution avec map est correcte. Mais vous parcourez le tableau entier à chaque recherche. Ce n'est que le pire des cas pour findIndex qui arrête l'itération une fois qu'une correspondance est trouvée.


Il n'y a pas vraiment de manière concise (quand les développeurs ont dû s'inquiéter de IE8) , mais voici un commun solution:
var searchTerm = "stevie",
    index = -1;
for(var i = 0, len = myArray.length; i < len; i++) {
    if (myArray[i].hello === searchTerm) {
        index = i;
        break;
    }
}

, Ou en fonction:

function arrayObjectIndexOf(myArray, searchTerm, property) {
    for(var i = 0, len = myArray.length; i < len; i++) {
        if (myArray[i][property] === searchTerm) return i;
    }
    return -1;
}
arrayObjectIndexOf(arr, "stevie", "hello"); // 1

Juste quelques remarques:

  1. ne pas utiliser for...in boucles sur les tableaux
  2. assurez-vous de sortir de la boucle ou de retour de la fonction une fois que vous avez trouvé votre "aiguille"
  3. soyez prudent avec l'égalité des objets

Par exemple

var a = {obj: 0};
var b = [a];
b.indexOf({obj: 0}); // -1 not found
274
répondu Joe 2017-06-28 13:01:15

Dans ES2015, c'est assez facile:

myArray.map(x => x.hello).indexOf('stevie')

Ou, probablement avec de meilleures performances pour les tableaux plus grands:

myArray.findIndex(x => x.hello === 'stevie')
87
répondu Steve Bennett 2016-09-21 06:00:11
var idx = myArray.reduce( function( cur, val, index ){

    if( val.hello === "stevie" && cur === -1 ) {
        return index;
    }
    return cur;

}, -1 );
24
répondu Esailija 2011-12-29 13:03:32

J'aime la réponse de Pablo, mais Array # indexOf et Array # map ne fonctionnent pas sur tous les navigateurs. Underscore utilisera du code natif s'il est disponible, mais a également des solutions de repli. De plus, il a la méthode pluck pour faire exactement ce que fait la méthode de carte anonyme de Pablo.

var idx = _.chain(myArray).pluck("hello").indexOf("Stevie").value();
18
répondu tandrewnichols 2014-05-08 10:35:10

Ou prototype:

Array.prototype.indexOfObject = function arrayObjectIndexOf(property, value) {
    for (var i = 0, len = this.length; i < len; i++) {
        if (this[i][property] === value) return i;
    }
    return -1;
}

myArr.indexOfObject("name", "stevie");
15
répondu Nathan Zaetta 2016-02-26 00:05:03

Bref

myArray.indexOf('stevie','hello')

Cas D'Utilisation:

  /*****NORMAL****/  
[2,4,5].indexOf(4) ;//OUTPUT 1
 /****COMPLEX*****/
 [{slm:2},{slm:4},{slm:5}].indexOf(4,'slm');//OUTPUT 1
 //OR
 [{slm:2},{slm:4},{slm:5}].indexOf(4,function(e,i){
   return e.slm;
});//OUTPUT 1
/***MORE Complex**/
[{slm:{salat:2}},{slm:{salat:4}},{slm:{salat:5}}].indexOf(4,function(e,i){
   return e.slm.salat;
});//OUTPUT 1

API:

    Array.prototype.indexOfOld=Array.prototype.indexOf

    Array.prototype.indexOf=function(e,fn){
      if(!fn){return this.indexOfOld(e)}
      else{ 
       if(typeof fn ==='string'){var att=fn;fn=function(e){return e[att];}}
        return this.map(fn).indexOfOld(e);
      }
    };
8
répondu Abdennour TOUMI 2014-11-09 12:38:36
array.filter(function(item, indx, arr){ return(item.hello === 'stevie'); })[0];

Attention au [0].

Il est correct d'utiliser reduce comme dans la réponse de Antonio Laguna.

Toutes mes excuses pour la brièveté...

4
répondu Cody 2014-06-12 17:40:14

J'ai fait quelques tests de performance de diverses réponses ici, que n'importe qui peut les exécuter soi-même:

Https://jsperf.com/find-index-of-object-in-array-by-contents

Sur la base de mes tests initiaux dans Chrome, la méthode suivante (en utilisant une boucle for configurée dans un prototype) est la plus rapide:

Array.prototype.indexOfObject = function (property, value) {
    for (var i = 0, len = this.length; i < len; i++) {
        if (this[i][property] === value) return i;
    }
    return -1;
}

myArray.indexOfObject("hello", "stevie");

Ce code est une version légèrement modifiée de la réponse de Nathan Zaetta.

Dans les benchmarks de performance, Je l'ai essayé avec à la fois la cible étant au milieu (index 500) et très fin (index 999) d'un tableau d'objets 1000, et même si je mets la cible en tant que dernier élément du tableau (ce qui signifie qu'il doit parcourir chaque élément du tableau avant qu'il ne soit trouvé), il finit toujours le plus rapide.

Cette solution a également l'avantage d'être l'une des plus laconiques pour l'exécution répétée, puisque seule la dernière ligne doit être répétée:

myArray.indexOfObject("hello", "stevie");
4
répondu Uniphonic 2017-06-27 22:21:54

Simple:

myArray.indexOf(myArray.filter(function(item) {
    return item.hello == "stevie"
})[0])
3
répondu griffon vulture 2016-05-18 10:11:45

Si vous êtes seulement intéressé à trouver le poste, consultez la réponse de @Pablo .

pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie');

Cependant, si vous êtes impatient de trouver l'élément (c'est-à-dire si vous envisagez de faire quelque chose comme ça myArray[pos]), il existe un moyen plus efficace de le faire en utilisantfilter.

element = myArray.filter((e) => e.hello === 'stevie')[0];

Voir les résultats de performance (~+42% ops / sec): http://jsbench.github.io/#7fa01f89a5dc5cc3bee79abfde80cdb3

3
répondu zurfyx 2017-05-23 11:47:29

J'ai comparé plusieurs méthodes et j'ai reçu un résultat avec le moyen le plus rapide de résoudre ce problème. C'est une boucle for. C'est 5 fois plus rapide que toute autre méthode.

Voici la page du test: https://jsbench.me/9hjewv6a98

3
répondu John Klimov 2018-03-18 14:58:08

Voir cet exemple: http://jsfiddle.net/89C54/

for (i = 0; i < myArray.length; i++) {
    if (myArray[i].hello === 'stevie') {
        alert('position: ' + i);
        return;
    }
}

Il commence à compter avec zéro.

2
répondu Armin 2011-12-29 13:10:17

J'ai fait une fonction générique pour vérifier que ci-dessous est le code et fonctionne pour n'importe quel objet

function indexOfExt(list, item) {
    var len = list.length;

    for (var i = 0; i < len; i++) {
        var keys = Object.keys(list[i]);
        var flg = true;
        for (var j = 0; j < keys.length; j++) {
            var value = list[i][keys[j]];
            if (item[keys[j]] !== value) {
                flg = false;
            }
        }
        if (flg == true) {
            return i;
        }
    }
    return -1;
}

var items = [{ "hello": 'world', "foo": 'bar' }];
var selectedItem = { "hello": 'world', "foo": 'bar' };
alert(items.indexOf(selectedItem));
alert(indexOfExt(items, selectedItem));

La première alerte retournera -1 (signifie match introuvable) et la deuxième alerte retournera 0 (signifie match trouvé).

2
répondu Shiljo 2015-04-22 14:17:33

Utiliser _.findIndex à partir de trait de soulignement.bibliothèque js

Voici l'exemple _.findIndex([{a:1},{a: 2,c:10},{a: 3}], {a:2,c:10}) //1

2
répondu niren 2015-08-11 03:06:31

Essayez ceci:

console.log(Object.keys({foo:"_0_", bar:"_1_"}).indexOf("bar"));

Https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

2
répondu John Doe 2016-04-12 17:14:19

Vous pouvez utiliser une fonction native et pratique Array.prototype.findIndex() fondamentalement:

La méthode findIndex () renvoie un index dans le tableau, si un élément du tableau satisfait la fonction de test fournie. Sinon, -1 est retourné.

Juste une note, il n'est pas pris en charge sur Internet Explorer, Opera et Safari, mais vous pouvez utiliser un Polyfill fourni dans le lien ci-dessous.

Plus informations:

Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

var hello = {
  hello: 'world',
  foo: 'bar'
};
var qaz = {
  hello: 'stevie',
  foo: 'baz'
}

var myArray = [];
myArray.push(hello, qaz);

var index = myArray.findIndex(function(element, index, array) {
  if (element.hello === 'stevie') {
    return true;
  }
});
alert('stevie is at index: ' + index);
2
répondu GibboK 2016-06-10 09:19:54

Plus loin de @Monika Garg réponse , Vous pouvez utiliser findIndex() (Il y a un polyfill pour les navigateurs non supprimés).

J'ai vu que les gens ont rejeté cette réponse, et j'espère qu'ils l'ont fait à cause de la mauvaise syntaxe, car à mon avis, c'est la façon la plus élégante.

La méthode findIndex () renvoie un index dans le tableau, si un élément du tableau satisfait la fonction de test fournie. Sinon, -1 est retourné.

Par exemple:

var hello = {
  hello: 'world',
  foo: 'bar'
};
var qaz = {
  hello: 'stevie',
  foo: 'baz'
}

var myArray = [];
myArray.push(hello,qaz);

var index = myArray.findIndex(function(element) {
  return element.hello == 'stevie';
});

alert(index);
2
répondu Mosh Feu 2017-05-23 12:10:47

C'est la façon de trouver l'objet de l'indice dans le tableau

    var myArray = [{  hello: 'world',
        foo: 'bar'
    },{
        hello: 'stevie',
        foo: 'baz'
    }];



    for (i = 0; i < myArray.length; i++) {
        if (myArray[i].hello === 'stevie') {
            alert('position: ' + i);
            return;
        }
    }
1
répondu Asad Fida 2015-01-09 12:51:42

Utilisation de L'ES6 findIndex Méthode , sans lodash ou toute autre bibliothèque, vous pouvez écrire:

function deepIndexOf(arr, obj) {
  return arr.findIndex(function (cur) {
    return Object.keys(obj).every(function (key) {
      return obj[key] === cur[key];
    });
  });
}

Cela comparera les propriétés immédiates de l'objet, mais pas les récursivité dans les propriétés.

Si votre implémentation ne fournit pas encore findIndex (la plupart ne le font pas), vous pouvez ajouter un polyfill léger qui prend en charge cette recherche:

function deepIndexOf(arr, obj) {
  function findIndex = Array.prototype.findIndex || function (pred) {
    for (let i = 0; i < this.length; ++i) {
      if (pred.call(this, this[i], i)) {
        return i;
      }
    }

    return -1;
  }

  return findIndex.call(arr, function (cur) {
    return Object.keys(obj).every(function (key) {
      return obj[key] === cur[key];
    });
  });
}

(dans ma réponse sur cette dupe)

1
répondu ssube 2017-05-23 11:55:10

Si votre objet est le même objet que celui que vous utilisez dans le tableau, vous devriez pouvoir obtenir l'index de l'objet de la même manière que si c'était une chaîne.

var hello = {
    hello: 'world',
    foo: 'bar'
};
var qaz = {
    hello: 'stevie',
    foo: 'baz'
}

var qazCLONE = { // new object instance and same structure
    hello: 'stevie',
    foo: 'baz'
}

var myArray = [hello,qaz];

myArray.indexOf(qaz) // should return 1
myArray.indexOf(qazCLONE) // should return -1
1
répondu Caio Koiti 2018-02-09 08:39:52

Alors que, la plupart des autres réponses ici sont valides. Parfois, il est préférable de simplement faire une courte FONCTION simple près de l'endroit où vous l'utiliserez.

// indexOf wrapper for the list of objects
function indexOfbyKey(obj_list, key, value) {
    for (index in obj_list) {
        if (obj_list[index][key] === value) return index;
    }
    return -1;
}
// Find the string in the list (default -1)
var test1 = indexOfbyKey(object_list, 'name', 'Stevie');
var test2 = indexOfbyKey(object_list, 'last_name', 'some other name');

Cela dépend de ce qui est important pour vous. Il pourrait sauver des lignes de code et être très intelligent d'utiliser un one-liner, ou de mettre une solution générique quelque part qui couvre divers cas de bord. Mais parfois, il vaut mieux simplement dire: "ici, je l'ai fait comme ça" plutôt que de laisser les futurs développeurs avoir un travail d'ingénierie inverse supplémentaire. Surtout si vous considérez - vous comme "un débutant" comme dans votre question.

1
répondu SpiRail 2018-04-02 20:56:31

, Vous pouvez simplement utiliser

const someId = 2;
const array = [{id:1}, {id:2}, {id:3}];
const index = array.reduce((i, item, index) => item.id === someId ? index : i, -1);
alert('someId ' + someId + ' is at index ' + index);

Pas de soulignement, pas pour, juste une réduction.

0
répondu 7ynk3r 2016-06-14 05:11:36
var hello = {hello: "world",  foo: "bar"};
var qaz = {hello: "stevie", foo: "baz"};
var myArray = [];
myArray.push(hello,qaz);

function indexOfObject( arr, key, value   ) {
    var j = -1;
    var result = arr.some(function(obj, i) { 
        j++;
        return obj[key] == value;
    })

    if (!result) {
        return -1;
    } else {
        return j;
    };
}

alert(indexOfObject(myArray,"hello","world"));
0
répondu user3235365 2017-11-05 23:33:54

, Vous pouvez créer votre propre prototype pour ce faire:

Quelque Chose comme:

Array.prototype.indexOfObject = function (object) {
    for (var i = 0; i < this.length; i++) {
        if (JSON.stringify(this[i]) === JSON.stringify(object))
            return i;
    }
}
-1
répondu Janx from Venezuela 2014-04-17 22:29:10

Cela fonctionne sans code personnalisé

var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true

Note: cela ne donne pas l'index réel, il indique seulement si votre objet existe dans la structure de données actuelle

-1
répondu Xeltor 2015-08-03 14:29:00

Je préfère utiliser findIndex() méthode:

 var index = myArray.findIndex('hello','stevie');

index vous donnera le numéro d'index.

-2
répondu Monika Garg 2014-05-29 05:06:43