web-dev-qa-db-de.com

Liefert den Schleifenzähler/-index für… der Syntax in JavaScript

Vorsicht:

die Frage gilt weiterhin für for…of-Schleifen.> Verwenden Sie for…in nicht zum Durchlaufen eines Arrays , sondern zum Durchlaufen von über den properties eines Objekts. Das sagte, das hier


Ich verstehe, dass die grundlegende for…in-Syntax in JavaScript folgendermaßen aussieht:

for (var obj in myArray) {
    // ...
}

Aber wie bekomme ich die Schleife counter/index

Ich weiß, ich könnte wahrscheinlich so etwas tun:

var i = 0;
for (var obj in myArray) {
    alert(i)
    i++
}

Oder sogar das gute Alte:

for (var i = 0; 1 < myArray.length; i++) {
    var obj = myArray[i]
    alert(i)
}

Ich würde aber lieber die einfachere for-in-Schleife verwenden. Ich finde, sie sehen besser aus und sind sinnvoller.

Gibt es einen einfacheren oder eleganteren Weg?


In Python ist es einfach:

for i, obj in enumerate(myArray):
    print i
171
hobbes3

_for…in_ iteriert über Eigenschaftsnamen, nicht über Werte, und zwar in nicht angegebener Reihenfolge (ja, auch nach ES6). Sie sollten es nicht verwenden, um Arrays zu durchlaufen. Für sie gibt es die forEach -Methode von ES5, die sowohl den Wert als auch den Index an die von Ihnen angegebene Funktion übergibt:

_var myArray = [123, 15, 187, 32];

myArray.forEach(function (value, i) {
    console.log('%d: %s', i, value);
});

// Outputs:
// 0: 123
// 1: 15
// 2: 187
// 3: 32
_

Oder ES6s Array.prototype.entries , das jetzt in allen aktuellen Browserversionen unterstützt wird:

_for (const [i, value] of myArray.entries()) {
    console.log('%d: %s', i, value);
}
_

Für Iterables im Allgemeinen (bei denen Sie eine _for…of_ -Schleife anstelle einer _for…in_ verwenden würden) ist jedoch nichts integriert:

_function* enumerate(iterable) {
    let i = 0;

    for (const x of iterable) {
        yield [i, x];
        i++;
    }
}

for (const [i, obj] of enumerate(myArray)) {
    console.log(i, obj);
}
_

Demo

Wenn Sie tatsächlich _for…in_ - Auflisten von Eigenschaften - gemeint hätten, bräuchten Sie einen zusätzlichen Leistungsindikator. Object.keys(obj).forEach könnte funktionieren, enthält aber nur eigene Eigenschaften; _for…in_ enthält überall in der Prototypenkette zahlreiche Eigenschaften.

390
Ry-

In ES6 ist es ratsam, for - of loop . Zu verwenden. Sie können Index für so erhalten

for (let [index, val] of array.entries()) {
        // your code goes here    
}

Beachten Sie, dass Array.entries()einen Iterator zurückgibt, wodurch er in der for-of-Schleife arbeiten kann. Verwechseln Sie dies nicht mit Object.entries () , das ein array von Schlüsselwertpaaren zurückgibt. 

94
rushUp

Lösung für kleine Array-Sammlungen:

for (var obj in arr) {
    var i = Object.keys(arr).indexOf(obj);
}

arr - ARRAY, obj - TASTE des aktuellen Elements i - COUNTER/INDEX

Notice: Methode keys () ist für IE Version <9 nicht verfügbar. Sie sollten Polyfill code . https: //developer.mozilla) verwenden .org/de/docs/Web/JavaScript/Referenz/Globale_Objekte/Objekt/Schlüssel

15
iwasborntobleed

For-in-Loops durchlaufen die Eigenschaften eines Objekts. Verwenden Sie sie nicht für Arrays, auch wenn sie manchmal funktionieren.

Objekteigenschaften haben dann keinen Index, sie sind alle gleich und müssen nicht in einer bestimmten Reihenfolge durchlaufen werden. Wenn Sie Eigenschaften zählen möchten, müssen Sie den zusätzlichen Zähler einrichten (wie in Ihrem ersten Beispiel).

schleife über ein Array:

var a = [];
for (var i=0; i<a.length; i++) {
    i // is the index
    a[i] // is the item
}

schleife über ein Objekt:

var o = {};
for (var prop in o) {
    prop // is the property name
    o[prop] // is the property value - the item
}
12
Bergi

Wie wäre es damit

let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))

Bei array.forEach hat diese Methode einen index-Parameter, der dem Index des aktuellen Elements entspricht, das im Array verarbeitet wird.

9
Sanjay Shr

Wie andere schon gesagt haben, sollten Sie nicht for..in verwenden, um ein Array zu durchlaufen.

for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }

Wenn Sie eine sauberere Syntax wünschen, können Sie forEach verwenden:

myArray.forEach( function ( val, i ) { ... } );

Wenn Sie diese Methode verwenden möchten, stellen Sie sicher, dass Sie das ES5-Shim mit einschließen, um Unterstützung für ältere Browser hinzuzufügen.

5
Robert Messerle

Hier ist eine Funktion eachWithIndex, die mit allem funktioniert, das durchlaufen werden kann.

Sie könnten auch eine ähnliche Funktion eachWithKey schreiben, die mit Objekten mit for...in funktioniert.

// example generator (returns an iterator that can only be iterated once)
function* eachFromTo(start, end) { for (let i = start; i <= end; i++) yield i }

// convers an iterable to an array (potential infinite loop)
function eachToArray(iterable) {
    const result = []
    for (const val of iterable) result.Push(val)
    return result
}

// yields every value and index of an iterable (array, generator, ...)
function* eachWithIndex(iterable) {
    const shared = new Array(2)
    shared[1] = 0
    for (shared[0] of iterable) {
        yield shared
        shared[1]++
    }
}

console.log('iterate values and indexes from a generator')
for (const [val, i] of eachWithIndex(eachFromTo(10, 13))) console.log(val, i)

console.log('create an array')
const anArray = eachToArray(eachFromTo(10, 13))
console.log(anArray)

console.log('iterate values and indexes from an array')
for (const [val, i] of eachWithIndex(anArray)) console.log(val, i)

Das Gute an Generatoren ist, dass sie faul sind und das Ergebnis eines anderen Generators als Argument akzeptieren können.

0
Rivenfall

Das ist meine Version eines zusammengesetzten Iterators, der einen Index und den Wert einer übergebenen Generatorfunktion mit einem Beispiel für eine (langsame) Primärsuche liefert:

const eachWithIndex = (iterable) => {
  return {
    *[Symbol.iterator]() {
      let i = 0
      for(let val of iteratable) {
        i++
          yield [i, val]
      }
    }
  }

}

const isPrime = (n) => {
  for (i = 2; i < Math.floor(Math.sqrt(n) + 1); i++) {
    if (n % i == 0) {
      return false
    }
  }
  return true
}

let primes = {
  *[Symbol.iterator]() {
    let candidate = 2
    while (true) {
      if (isPrime(candidate)) yield candidate
        candidate++
    }
  }
}

for (const [i, prime] of eachWithIndex(primes)) {
  console.log(i, prime)
  if (i === 100) break
}
0
akurtser