Accès à l'index des éléments du tableau ES6 dans la boucle for-of


228

Nous pouvons accéder aux éléments du tableau à l'aide d'une boucle for-of:

for (const j of [1, 2, 3, 4, 5]) {
  console.log(j);
}

Comment puis-je modifier ce code pour accéder à l'index en cours également? Je veux y parvenir en utilisant la syntaxe for-of, ni forEach ni for-in.

Réponses:


351

Utilisation Array.prototype.keys:

for (const index of [1, 2, 3, 4, 5].keys()) {
  console.log(index);
}

Si vous souhaitez accéder à la fois à la clé et à la valeur, vous pouvez utiliser Array.prototype.entries()avec la déstructuration :

for (const [index, value] of [1, 2, 3, 4, 5].entries()) {
  console.log(index, value);
}


64
Au cas où quelqu'un se demanderait, j'ai testé for-ofavec .entries()et c'est deux fois plus lent que .forEach(). jsperf.com/for-of-vs-foreach-with-index

1
@ K48 bon à savoir, utilisez "for-loop inversé" si vous voulez avoir le plus rapide en es: incroyable-web.com/blog/…
nimo23

3
Malheureusement, je dois céder de l'intérieur d'une boucle imbriquée. Impossible d'utiliser forEach, car la fonction crée des problèmes de portée pour le yieldmot clé. Mais j'ai besoin d'accéder à l'index pour mon cas d'utilisation, donc ... ancienne ;;boucle de base , je suppose.
Kyle Baker

2
@KyleBaker Et qu'est-ce qui ne va pas avec une boucle for-of .entires()?
Michał Perłakowski

1
Au lieu de la boucle inverse, vous pouvez mettre en cache la longueur jsperf.com/reverse-loop-vs-cache . Utile pour un traitement itérable lorsque vous pouvez traiter un flux sans créer de grands tableaux dans la RAM. La vitesse de boucle ne serait pas un goulot d'étranglement puisque vous aurez une latence d'E / S dans de tels cas.
x'ES

289

Array#entries renvoie l'index et la valeur, si vous avez besoin des deux:

for (let [index, value] of array.entries()) {

}

3
Avec TypeScript: 'TS2495: Type IterableIterator n'est pas un type de tableau ou un type de chaîne'. On dirait que cela sera résolu: github.com/Microsoft/TypeScript/pull/12346
Johannes

2
Internet Explorer n'est pas non plus pris en charge.
Sammi

1
Pas gentil. Lance une erreur, par exemple avec document.styleSheets[0].cssRules.entries()ou même document.styleSheets.entries()et probablement de nombreuses autres structures itératives DOM. Il faut encore utiliser _.forEach()delodash
Steven Pribilinskiy

2
@Steven: Si vous n'avez pas besoin de l'index, vous pouvez simplement le faire for (var value of document.styleSheets) {}. Si vous avez besoin l'index que vous pouvez convertir la valeur à un tableau d' abord par Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Felix Kling

1
C'est zonte! Array.fromest FTW
Steven Pribilinskiy

28

Dans ce monde de nouvelles fonctions natives flashy, nous oublions parfois les bases.

for (let i = 0; i < arr.length; i++) {
    console.log('index:', i, 'element:', arr[i]);
}

Propre, efficace et vous pouvez toujours faire breakla boucle. Prime! Vous pouvez également commencer par la fin et revenir en arrière avec i--!

Remarque supplémentaire: Si vous utilisez beaucoup la valeur dans la boucle, vous pouvez le faire const value = arr[i];en haut de la boucle pour une référence facile et lisible.


1
Oui. Bon, clair et simple. Oh, et comme ça, vous avez un moyen super facile d'accéder à la clé / index du tableau.
Combinez

2
Soit dit en passant, la condition devrait ressembler à ceci -> for (soit i = 0; i <arr.length; i ++) sans le (-1) ou elle ne bouclera pas sur tous les éléments du tableau.
Combinez

1
@Combine Bonne prise! J'ai mis à jour ma réponse pour refléter votre note.
chris

4
Vous pouvez toujours breakun for-ofet for (let [index, value] of array.entries())est beaucoup plus facile à lire. Revenir en arrière est aussi simple que d'ajouter .reverse().
Nigel B.Peck

3
Je pense que c'est une réponse parfaitement acceptable à cette question. Ce ne sera jamais la réponse acceptée, mais cela a aidé quelques dizaines de personnes ou plus qui ont cherché cette question. C'est à ça que sert SO.
Danoram

3

dans le contexte html / js, sur les navigateurs modernes, avec d'autres objets itérables que les tableaux, nous pourrions également utiliser [Iterable] .entries ():

for(let [index, element] of document.querySelectorAll('div').entries()) {

    element.innerHTML = '#' + index

}

Oui, cela fonctionne, tandis que d'autres mentionnées ci-dessus par @Steven Pribilinskiy, d'autres méthodes DOM retournent des objets qui n'ont pas de entriesméthode pour elles.
matanster

3

En for..ofboucle, nous pouvons y parvenir via array.entries(). array.entriesrenvoie un nouvel objet itérateur Array. Un objet itérateur sait comment accéder aux éléments à partir d'un objet itérable à la fois, tout en gardant une trace de sa position actuelle dans cette séquence.

Lorsque la next()méthode est appelée, les paires valeur / clé de l'itérateur sont générées. Dans ces paires de valeurs de clé, l' index du tableau est la clé et l'élément de tableau est la valeur.

let arr = ['a', 'b', 'c'];
let iterator = arr.entries();
console.log(iterator.next().value); // [0, 'a']
console.log(iterator.next().value); // [1, 'b']

Une for..ofboucle est fondamentalement une construction qui consomme un itérable et boucle à travers tous les éléments (en utilisant un itérateur sous le capot). Nous pouvons combiner cela avec array.entries()de la manière suivante:

array = ['a', 'b', 'c'];

for (let indexValue of array.entries()) {
  console.log(indexValue);
}


// we can use array destructuring to conveniently
// store the index and value in variables
for (let [index, value] of array.entries()) {
   console.log(index, value);
}


3

Vous pouvez également gérer l'index vous-même si vous avez besoin de l' index , cela ne fonctionnera pas si vous avez besoin de la clé .

let i = 0;
for (const item of iterableItems) {
  // do something with index
  console.log(i);

  i++;
}

0

Pour ceux qui utilisent des objets qui ne sont pas un Arraytableau ou même un tableau, vous pouvez facilement créer votre propre itérable afin que vous puissiez toujours l'utiliser for ofpour des choses comme celles localStoragequi n'ont vraiment que length:

function indexerator(length) {
    var output = new Object();
    var index = 0;
    output[Symbol.iterator] = function() {
        return {next:function() {
            return (index < length) ? {value:index++} : {done:true};
        }};
    };
    return output;
}

Ensuite, donnez-lui simplement un numéro:

for (let index of indexerator(localStorage.length))
    console.log(localStorage.key(index))

0

es6 for...in

for(const index in [15, 64, 78]) {                        
    console.log(index);
}

5
La question se pose sur une for...ofboucle pas unfor...in
Abraham Hernandez

3
for...infait partie de la spécification ECMAScript d'origine (ie "es1"). Notez également que cela for...inest destiné à itérer sur les propriétés des objets. Bien qu'il puisse parcourir les tableaux, il peut ne pas le faire dans l'ordre attendu. Voir plus dans la documentation MDN
Boaz

0

Une autre approche pourrait être en utilisant Array.prototype.forEach()comme

Array.from({
  length: 5
}, () => Math.floor(Math.random() * 5)).forEach((val, index) => {
  console.log(val, index)
})


-6
var fruits = ["apple","pear","peach"];
for (fruit of fruits) {
    console.log(fruits.indexOf(fruit));
    //it shows the index of every fruit from fruits
}

la boucle for traverse le tableau, tandis que la propriété indexof prend la valeur de l'index qui correspond au tableau. PD cette méthode a quelques défauts avec les nombres, donc utilisez des fruits


2
Cela prend du temps O (n ^ 2).
Harry

3
Dans les cas où les performances ne sont pas importantes, cela ne donne toujours pas tous les index corrects lorsqu'il y a des fruits en double. Par exemple, pour ["apple", "apple", "pear"]les index donnés sont 0, 0, 2au lieu de 0, 1, 2.
trichoplax
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.