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.
À 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.
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.
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'})
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.
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);
});
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
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 textevar 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)
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 .
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);
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é.
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.
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
}
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.