Caution:
question still applies to
for…of
loops.> Don\'t usefor…in
to iterate over an Array, use it
Answer Given by rushUp Is correct but this will be more convenient
for (let [index, val] of array.entries() || []) {
// your code goes here
}
In ES6, it is good to use for - of loop. You can get index in for of like this
for (let [index, val] of array.entries()) {
// your code goes here
}
Note that Array.entries()
returns an iterator, which is what allows it to work in the for-of loop; don't confuse this with Object.entries(), which returns an array of key-value pairs.
That's my version of a composite iterator that yields an index and any passed generator function's value with an example of (slow) prime search:
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
}
On top of the very good answers everyone posted I want to add that the most performant solution is the ES6 entries
. It seems contraintuitive for many devs here, so I created this perf benchamrk.
It's ~6 times faster. Mainly because doesn't need to: a) access the array more than once and, b) cast the index.
How about this
let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))
Where array.forEach
this method has an index
parameter which is the index of the current element being processed in the array.
Here's a function eachWithIndex
that works with anything iterable.
You could also write a similar function eachWithKey
that works with objets using for...in
.
// 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)
The good thing with generators is that they are lazy and can take another generator's result as an argument.