web-dev-qa-db-fra.com

Récupère l'index de l'objet dans un tableau, correspondant à une condition

J'ai un tableau comme celui-ci:

[{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"},...]

Comment puis-je obtenir l'index de l'objet qui correspond à une condition, sans itérer sur l'ensemble du tableau?

Par exemple, étant donné prop2=="yutu", je veux obtenir l'index 1.

J'ai vu .indexOf() mais je pense que c'est utilisé pour des tableaux simples comme ["a1","a2",...]. J'ai aussi vérifié $.grep() mais cela retourne des objets, pas l'index.

248
amp

À partir de 2016, vous êtes censé utiliser Array.findIndex (une norme ES2015/ES6) pour cela:

_a = [
  {prop1:"abc",prop2:"qwe"},
  {prop1:"bnmb",prop2:"yutu"},
  {prop1:"zxvz",prop2:"qwrq"}];
    
index = a.findIndex(x => x.prop2 ==="yutu");

console.log(index);_

Il est pris en charge par Google Chrome, Firefox et Edge. Pour Internet Explorer, il existe un polyfill sur la page liée.

Note de performance

Les appels de fonctions sont coûteux. Par conséquent, avec de très grands tableaux, une simple boucle donnera de bien meilleurs résultats que findIndex:

_let test = [];

for (let i = 0; i < 1e6; i++)
    test.Push({prop: i});


let search = test.length - 1;
let count = 100;

console.time('findIndex/predefined function');
    let fn = obj => obj.prop === search;

    for (let i = 0; i < count; i++)
        test.findIndex(fn);
console.timeEnd('findIndex/predefined function');


console.time('findIndex/dynamic function');
    for (let i = 0; i < count; i++)
        test.findIndex(obj => obj.prop === search);
console.timeEnd('findIndex/dynamic function');


console.time('loop');
    for (let i = 0; i < count; i++) {
        for (let index = 0; index < test.length; index++) {
            if (test[index].prop === search) {
                break;
            }
        }
    }
console.timeEnd('loop');_

Comme avec la plupart des optimisations, cela doit être appliqué avec précaution et uniquement lorsque cela est réellement nécessaire.

569
georg

Comment puis-je obtenir l'index de l'objet qui correspond à une condition (sans itérer le long du tableau)?

Vous ne pouvez pas, quelque chose doit parcourir le tableau (au moins une fois).

Si la condition change beaucoup, vous devrez alors parcourir les objets et voir s'ils correspondent à la condition. Toutefois, sur un système doté de fonctionnalités ES5 (ou si vous installez une cale), cette itération peut être effectuée de manière assez concise:

_var index;
yourArray.some(function(entry, i) {
    if (entry.prop2 == "yutu") {
        index = i;
        return true;
    }
});
_

Celui-ci utilise la fonction new (ish) Array#some , qui parcourt les entrées du tableau jusqu'à ce que la fonction que vous lui donnez retourne vraie. La fonction que je lui ai donnée enregistre l'index de l'entrée correspondante, puis renvoie true pour arrêter l'itération.

Ou bien sûr, utilisez simplement une boucle for. Vos différentes options d'itération sont couvertes dans cette autre réponse .

Mais si vous utilisez toujours la même propriété pour cette recherche, et si les valeurs de la propriété sont uniques, vous pouvez effectuer une boucle unique et créer un objet pour les mapper:

_var prop2map = {};
yourArray.forEach(function(entry) {
    prop2map[entry.prop2] = entry;
});
_

(Ou encore, vous pouvez utiliser une boucle for ou n’importe laquelle de vos autres options .)

Ensuite, si vous devez rechercher l'entrée avec _prop2 = "yutu"_, vous pouvez procéder comme suit:

_var entry = prop2map["yutu"];
_

J'appelle cela "l'indexation croisée" du tableau. Naturellement, si vous supprimez ou ajoutez des entrées (ou modifiez leurs valeurs _prop2_), vous devez également mettre à jour votre objet de mappage.

25
T.J. Crowder

Ce que TJ Crowder a dit a toujours une sorte d’itération cachée, avec lodash cela devient:

var index = _.findIndex(array, {prop2: 'yutu'})
20
aliak
var CarId = 23;

//x.VehicleId property to match in the object array
var carIndex = CarsList.map(function (x) { return x.VehicleId; }).indexOf(CarId);

Et pour les numéros de tableau de base, vous pouvez également le faire:

var numberList = [100,200,300,400,500];
var index = numberList.indexOf(200); // 1

Vous obtiendrez -1 s'il ne peut pas trouver une valeur dans le tableau.

11
David Castro
var index;
yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' ? (index = i, true) : false;
});

Itérer sur tous les éléments du tableau. Il renvoie soit l'index et true ou false si la condition ne correspond pas.

Important est la valeur de retour explicite de true (ou une valeur dont le résultat booléen est true). L'affectation unique n'est pas suffisante, en raison d'un index possible avec 0 (Boolean (0) === false), qui ne provoquerait pas d'erreur, mais désactive l'interruption de l'itération.

Modifier

Une version encore plus courte de ce qui précède:

yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' && ~(index = i);
});
11
Nina Scholz

Vous pouvez utiliser le Array.prototype.some () de la manière suivante (comme indiqué dans les autres réponses):

https://jsfiddle.net/h1d69exj/2/

function findIndexInData(data, property, value) {
    var result = -1;
    data.some(function (item, i) {
        if (item[property] === value) {
            result = i;
            return true;
        }
    });
    return result;
}
var data = [{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"}]



alert(findIndexInData(data, 'prop2', "yutu")); // shows index of 1
3
GibboK

J'ai vu beaucoup de solutions dans ce qui précède.

Ici, j'utilise la fonction map pour trouver l'index du texte recherché dans un objet tableau.

Je vais expliquer ma réponse en utilisant les données des élèves.

  • étape 1: créer un objet tableau pour les étudiants (facultatif, vous pouvez créer votre propre objet tableau).
    var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

  • étape 2: Créer une variable pour rechercher du texte
    var studentNameToSearch = "Divya";

  • étape: Créer une variable pour stocker l'index correspondant (ici, nous utilisons la fonction map pour itérer).
    var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);

var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

var studentNameToSearch = "Divya";

var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);

console.log(matchedIndex);

alert("Your search name index in array is:"+matchedIndex)
3
Rambabu Bommisetti

Pourquoi ne voulez-vous pas itérer exactement? Les nouveaux Array.prototype.forEach sont parfaits pour cela!

Vous pouvez utiliser un arbre de recherche binaire pour rechercher via un appel de méthode unique si vous le souhaitez. Ceci est une implémentation soignée de BTree et Red black Arbre de recherche dans JS - https://github.com/vadimg/js_bintrees - mais je ne suis pas sûr que vous puissiez trouver l'index en même temps .

1
Rishabh
function findIndexByKeyValue(_array, key, value) {
    for (var i = 0; i < _array.length; i++) { 
        if (_array[i][key] == value) {
            return i;
        }
    }
    return -1;
}
var a = [
    {prop1:"abc",prop2:"qwe"},
    {prop1:"bnmb",prop2:"yutu"},
    {prop1:"zxvz",prop2:"qwrq"}];
var index = findIndexByKeyValue(a, 'prop2', 'yutu');
console.log(index);
1
pranabesh chand

Une étape en utilisant Array.reduce () - pas de jQuery

var items = [{id: 331}, {id: 220}, {id: 872}];

var searchIndexForId = 220;
var index = items.reduce(function(searchIndex, item, index){
  if(item.id === searchIndexForId) { 
    console.log('found!');
    searchIndex = index;
  }
  return searchIndex;
}, null);

retournera null si l'index n'a pas été trouvé.

1
SagiSergeNadir

Optimiser le code:

var index;
yourArray.some(function(entry, i) {
    index = i;
    return entry.prop2 == "yutu";
});

Pourquoi tout ce qu'ils retournent vrai et faux.

0
Durgpal Singh
var list =  [
                {prop1:"abc",prop2:"qwe"},
                {prop1:"bnmb",prop2:"yutu"},
                {prop1:"zxvz",prop2:"qwrq"}
            ];

var findProp = p => {
    var index = -1;
    $.each(list, (i, o) => {
        if(o.prop2 == p) {
            index = i;
            return false; // break
        }
    });
    return index; // -1 == not found, else == index
}
0
Ruben Morales Felix

Georg a déjà mentionné que ES6 avait Array.findIndex pour cela. Et d'autres solutions sont une solution de contournement pour ES5 en utilisant la méthode Array.some.

Une approche plus élégante peut être

var index;
for(index = yourArray.length; index-- > 0 && yourArray[index].prop2 !== "yutu";);

En même temps, je voudrais souligner que Array.some peut être mis en œuvre avec une technique de recherche binaire ou autre. Ainsi, il pourrait être plus performant en boucle dans certains navigateurs.

0
Sanjoy