Get loop counter/index using for…of syntax in JavaScript
JavascriptFor LoopForeachCounterJavascript Problem Overview
> ###Caution:
>question still applies to for…of
loops.> Don't use for…in
to iterate over an Array, use it to iterate
> over the properties of an object. That said, this
I understand that the basic for…in
syntax in JavaScript looks like this:
for (var obj in myArray) {
// ...
}
But how do I get the loop counter/index?
I know I could probably do something like:
var i = 0;
for (var obj in myArray) {
alert(i)
i++
}
Or even the good old:
for (var i = 0; i < myArray.length; i++) {
var obj = myArray[i]
alert(i)
}
But I would rather use the simpler for-in
loop. I think they look better and make more sense.
Is there a simpler or more elegant way?
In Python it's easy:
for i, obj in enumerate(myArray):
print i
Javascript Solutions
Solution 1 - Javascript
for…in
iterates over property names, not values, and does so in an unspecified order (yes, even after ES6). You shouldn’t use it to iterate over arrays. For them, there’s ES5’s forEach
method that passes both the value and the index to the function you give it:
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
Or ES6’s Array.prototype.entries
, which now has support across current browser versions:
for (const [i, value] of myArray.entries()) {
console.log('%d: %s', i, value);
}
For iterables in general (where you would use a for…of
loop rather than a for…in
), there’s nothing built-in, however:
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);
}
If you actually did mean for…in
– enumerating properties – you would need an additional counter. Object.keys(obj).forEach
could work, but it only includes own properties; for…in
includes enumerable properties anywhere on the prototype chain.
Solution 2 - Javascript
In ES6, it is good to use a 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.
Solution 3 - Javascript
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.
Solution 4 - Javascript
Solution for small array collections:
for (var obj in arr) {
var i = Object.keys(arr).indexOf(obj);
}
arr - ARRAY, obj - KEY of current element, i - COUNTER/INDEX
Notice: Method keys() is not available for IE version <9, you should use Polyfill code. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Solution 5 - Javascript
For-in-loops iterate over properties of an Object. Don't use them for Arrays, even if they sometimes work.
Object properties then have no index, they are all equal and not required to be run through in a determined order. If you want to count properties, you will have to set up the extra counter (as you did in your first example).
loop over an Array:
var a = [];
for (var i=0; i<a.length; i++) {
i // is the index
a[i] // is the item
}
loop over an Object:
var o = {};
for (var prop in o) {
prop // is the property name
o[prop] // is the property value - the item
}
Solution 6 - Javascript
As others have said, you shouldn't be using for..in to iterate over an array.
for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }
If you want cleaner syntax, you could use forEach:
myArray.forEach( function ( val, i ) { ... } );
If you want to use this method, make sure that you include the ES5 shim to add support for older browsers.
Solution 7 - Javascript
Answer Given by rushUp Is correct but this will be more convenient
for (let [index, val] of array.entries() || []) {
// your code goes here
}
Solution 8 - Javascript
To use for..of loop on array and retrieve index you can you use array1.indexOf(element)
which will return the index value of an element in the loop. You can return both the index and the value using this method.
array1 = ['a', 'b', 'c']
for (element of array1) {
console.log(array1.indexOf(element), element) // 0 a 1 b 2 c
}
As mentionned in comments, this will return false index when the array contains non uniques values. (considering arr = ['a', 'b', 'c', 'a'], index of arr[3] will return 0 instead of 3)
Solution 9 - Javascript
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.
Solution 10 - Javascript
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.
Solution 11 - Javascript
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
}
Solution 12 - Javascript
By this for of loop system in js, you can find all arrays elements with index no ...
const menus = ['Bengali', 'Italiano', 'Americano', 'Thai', 'Chinese'];
for (const menus of menu.entries()) {
console.log(menus);
}