在 JavaScript 中使用 for...of 语法获取循环计数器/索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10179815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:11:23  来源:igfitidea点击:

Get loop counter/index using for…of syntax in JavaScript

javascriptfor-loopforeachcounter

提问by hobbes3

Caution:

question still applies to for…ofloops.> Don't use for…into iterate over an Array, use it to iterate over the propertiesof an object. That said, this

警告:

问题仍然适用于for…of循环。> 不要for…in用于迭代Array,使用它来迭代对象的属性。话说这个



I understand that the basic for…insyntax in JavaScript looks like this:

我了解for…inJavaScript中的基本语法如下所示:

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-inloop. I think they look better and make more sense.

但我宁愿使用更简单的for-in循环。我认为它们看起来更好,更有意义。

Is there a simpler or more elegant way?

有没有更简单或更优雅的方法?



In Python it's easy:

在 Python 中很容易:

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

回答by Ry-

for…initerates 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 forEachmethod that passes both the value and the index to the function you give it:

for…in迭代属性名称,而不是值,并以未指定的顺序进行(是的,即使在 ES6 之后)。您不应该使用它来迭代数组。对他们来说,有 ES5 的forEach方法可以将值和索引传递给你给它的函数:

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:

或者 ES6 的Array.prototype.entries,它现在支持跨当前浏览器版本:

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

For iterables in general (where you would use a for…ofloop rather than a for…in), there's nothing built-in, however:

对于一般的可迭代对象(您将使用for…of循环而不是 a for…in),没有任何内置内容,但是:

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

演示

If you actually did mean for…in– enumerating properties – you would need an additional counter. Object.keys(obj).forEachcould work, but it only includes ownproperties; for…inincludes enumerable properties anywhere on the prototype chain.

如果您确实是指for…in- 枚举属性 - 您将需要一个额外的计数器。Object.keys(obj).forEach可以工作,但它只包含自己的属性;for…in包括原型链上任何地方的可枚举属性。

回答by rushUp

In ES6, it is good to use for - of loop. You can get index in for of like this

在 ES6 中,最好使用 for - of 循环。你可以像这样获得索引

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 arrayof key-value pairs.

请注意,Array.entries()返回一个迭代器,它允许它在 for-of 循​​环中工作;不要将此与Object.entries()混淆,后者返回键值对数组

回答by Sanjay Shr

How about this

这个怎么样

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

Where array.forEachthis method has an indexparameter which is the index of the current element being processed in the array.

其中array.forEach,该方法具有一index参数,该参数是阵列中当前正在处理的元素的索引。

回答by iwasborntobleed

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

arr- ARRAY, obj- 当前元素的 KEY, i- COUNTER/INDEX

Notice:Method keys()is not available for IE version <9, you should use Polyfillcode. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

注意:方法keys()不适用于 IE 版本 <9,您应该使用Polyfill代码。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

回答by Bergi

For-in-loops iterate over properties of an Object. Don't use them for Arrays, even if they sometimes work.

For-in 循环迭代对象的属性。不要将它们用于数组,即使它们有时有效。

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
}

回答by Robert Messerle

As others have said, you shouldn't be using for..in to iterate over an array.

正如其他人所说,您不应该使用 for..in 来迭代数组。

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

If you want cleaner syntax, you could use forEach:

如果你想要更简洁的语法,你可以使用 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.

如果要使用此方法,请确保包含 ES5 shim 以添加对旧浏览器的支持。

回答by Renish Gotecha

Answer Given by rushUp Is correct but this will be more convenient

rushUp 给出的答案是正确的,但这会更方便

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

回答by sospedra

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.

除了每个人都发布的非常好的答案之外,我想补充一点,性能最高的解决方案是 ES6 entries。对于这里的许多开发人员来说,这似乎是有约束的,所以我创建了这个 perf benchamrk

enter image description here

在此处输入图片说明

It's ~6 times faster. Mainly because doesn't need to: a) access the array more than once and, b) cast the index.

它快了约 6 倍。主要是因为不需要:a) 多次访问数组,b) 转换索引。

回答by Rivenfall

Here's a function eachWithIndexthat works with anything iterable.

这是一个eachWithIndex适用于任何可迭代对象的函数。

You could also write a similar function eachWithKeythat works with objets using for...in.

您还可以eachWithKey使用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.

生成器的好处是它们很懒惰,可以将另一个生成器的结果作为参数。

回答by akurtser

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
}