जावास्क्रिप्ट में सिंटैक्स के… के लिए लूप काउंटर / इंडेक्स का उपयोग करें


317

सावधान:

प्रश्न अभी भी for…ofलूप्स पर लागू होता है ।> for…inएक ऐरे पर पुनरावृति करने के लिए उपयोग न करें , किसी ऑब्जेक्ट के गुणों पर पुनरावृति करने के लिए इसका उपयोग करें । उस ने कहा, यह


मैं समझता हूं कि for…inजावास्क्रिप्ट में मूल सिंटैक्स इस तरह दिखता है:

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

लेकिन मुझे लूप काउंटर / इंडेक्स कैसे मिलेगा ?

मुझे पता है कि मैं शायद ऐसा कुछ कर सकता हूं:

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

या यहां तक ​​कि पुराने अच्छे:

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

लेकिन मैं सरल for-inलूप का उपयोग करूंगा । मुझे लगता है कि वे बेहतर दिखते हैं और अधिक समझ बनाते हैं।

क्या कोई सरल या अधिक सुरुचिपूर्ण तरीका है?


पायथन में यह आसान है:

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

6
सरणियों के लिए ... के लिए उपयोग न करें। और वैसे भी, यह संपत्ति के नामों पर निर्भर करता है, गुणों के मूल्यों पर नहीं।
फेलिक्स क्लिंग

1
यह एक सरणी है, वस्तु नहीं है, है ना? तो alert(obj),?
रॉकेट हज़मत

जवाबों:


545

for…inयह संपत्ति के नामों पर निर्भर करता है, मूल्यों पर नहीं, और अनिर्दिष्ट क्रम में ऐसा करता है (हाँ, ईएस 6 के बाद भी)। आपको सरणियों पर पुनरावृति करने के लिए इसका उपयोग नहीं करना चाहिए। उनके लिए, ईएस 5 की 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

या ES6 की Array.prototype.entries, जिसका अब वर्तमान ब्राउज़र संस्करणों में समर्थन है:

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

सामान्य रूप से पुनरावृत्तियों के लिए (जहाँ आप एक for…ofलूप की बजाय 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);
}

डेमो

यदि आप वास्तव में मतलब था for…in- गुण की गणना - आप एक अतिरिक्त काउंटर की आवश्यकता होगी। Object.keys(obj).forEachकाम कर सकता था, लेकिन इसमें केवल स्वयं के गुण शामिल हैं; for…inप्रोटोटाइप श्रृंखला पर कहीं भी अनगिनत गुण शामिल हैं।


2
ओह ठीक। मैं भ्रमित था। मैंने सोचा कि जावास्क्रिप्ट के लिए पायथन के रूप में ही था। स्पष्टीकरण के लिए धन्यवाद।
hobbes3

1
@quantumpotato: lets varब्लॉक स्कोप के साथ हैं । consts अपरिवर्तित हैं।
Ry-

1
यह एक विस्तृत जवाब था, इसके लिए धन्यवाद। वास्तव में चर्चा की गई सभी बातों को स्पष्ट किया
धीरज भास्कर

1
बेवकूफ सवाल है, लेकिन क्या वास्तव में% d और% s के लिए खड़े हैं, या वे किसी भी पत्र हो सकता है मैं उन्हें होना चाहते हैं?
klewis

2
@klewis: %dपूर्णांक को %sस्वरूपित करता है और एक स्ट्रिंग को प्रारूपित करता है। वे प्रिंटफ पर आधारित हैं । कंसोल .spec.whatwg.org /# formatter पर एक युक्ति चल रही है ।
Ry-

162

ईएस 6 में, लूप के लिए उपयोग करना अच्छा है। आप इस तरह के लिए सूचकांक प्राप्त कर सकते हैं

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

ध्यान दें कि एक पुनरावृत्तArray.entries() रिटर्न , जो कि यह लूप के लिए काम करने की अनुमति देता है; Object.entries () के साथ इसे भ्रमित न करें , जो कुंजी-मूल्य जोड़े की एक सरणी देता है ।


9
यह स्वीकार किए जाते हैं की तुलना में एक बेहतर जवाब है!
त्रुक्त्र

3
मुझे लगता है कि यह समाधान forEach one से बेहतर है ... यह लूप सिंटैक्स के लिए ... का उपयोग करता है, और आपको एक अलग फ़ंक्शन का उपयोग करने की आवश्यकता नहीं है। दूसरे शब्दों में, यह वाक्यात्मक रूप से बेहतर है। ऐसा लगता है कि ओपी चाहता था।
u8y7541

1
entries()एक खाली वस्तु लौटा रहा है {}:। किसी भी विचार क्यों होगा? मेरा arrayवस्तुओं का एक सरणी है।
जोशुआ पिंटर

@JoshuaPinter के Object.entries(array)बजाय कोशिश करेंarray.entries()
tonyg

2
यह करने के लिए माना जाता है कि, यहोशू - वस्तु एक पुनरावृत्त है, एक next()विधि जिसके साथ यह कहा जाता है हर बार सरणी में बाद की प्रविष्टियों को वापस कर देगा। इसमें कोई (दृश्य) डेटा नहीं है; आपको कॉल करके अंतर्निहित ऑब्जेक्ट में डेटा मिलता है next(), जो पर्दे के पीछे करता है। cc @tonyg
Shog9

26

इस बारे में कैसा है

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

जहां array.forEachइस विधि में एक indexपैरामीटर है जो सरणी में संसाधित होने वाले वर्तमान तत्व का सूचकांक है।


1
यहाँ सबसे अच्छा जवाब
कोडप्लब

4
चुना हुआ उत्तर इस एक से 6 साल पहले पोस्ट किया गया था और इसमें पहले से ही वही बात है ...
देवी

फॉरआइस अनुकूलन के लिए अच्छा नहीं है, क्योंकि break उपलब्ध नहीं है।
स्मार्टवर्ल्ड-डीएम

19

छोटे सरणी संग्रह के लिए समाधान:

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

गिरफ्तारी - ARRAY, obj - वर्तमान तत्व का कुंजी, i - COUNTER / INDEX

नोटिस: विधि कुंजी () IE संस्करण <9 के लिए उपलब्ध नहीं है, आपको पॉलीफिल कोड का उपयोग करना चाहिए । https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys


7
मेरा सुझाव है: इसके बजाय एक काउंटर का उपयोग करें, इसे लूप में बढ़ाएँ।
मई

2
Mayankcpdixit पर जोड़ना, इसके बजाय एक काउंटर का उपयोग करें क्योंकि indexOf पर नकारात्मक प्रदर्शन प्रभाव पड़ सकता है।
डीन लियू

1
ऑब्जेक्ट जितना बड़ा होगा, यह उतना ही धीमा होगा। यह पैमाना नहीं है।
ढेकले

2
यह निरर्थक रूप से धीमी गति से की तरह है और क्योंकि जटिल है var i = 0;और i++;छोटे और अधिक सक्षम है। इसके अलावा यह उन गुणों के लिए काम नहीं करता है जो स्वयं के गुण नहीं हैं।
Ry-

1
@trusktr: और अगर यह आवश्यक है ... आपको अभी भी इसका उपयोग नहीं करना चाहिए। जब आप संग्रह को बदलते हैं तो काउंटर को बदल दें। अगर इसमें जगह नहीं है, तो इसके बजाय एक अच्छा कार्यात्मक परिवर्तन करें।
Ry-

13

किसी ऑब्जेक्ट के गुणों के लिए इन-लूप को पुन: व्यवस्थित करता है। Arrays के लिए उनका उपयोग न करें, भले ही वे कभी-कभी काम करते हों।

ऑब्जेक्ट प्रॉपर्टीज का कोई इंडेक्स नहीं है, वे सभी समान हैं और निर्धारित क्रम में चलाने की आवश्यकता नहीं है। यदि आप गुण गिनना चाहते हैं, तो आपको अतिरिक्त काउंटर स्थापित करना होगा (जैसा कि आपने अपने पहले उदाहरण में किया था)।

एक ऐरे पर लूप:

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

एक वस्तु पर पाश:

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

3
(var i=0; i<a.length; i++)संसाधनों को बर्बाद न करें । उपयोग(var i=0, var len = a.length; i<len; i++)
Félix Sanz

16
@FelixSanz: अपशिष्ट संसाधन? बिल्कुल नहीं। यह एक समयपूर्व सूक्ष्म अनुकूलन है जो शायद ही कभी आवश्यक है, और var i=0; i<a.length; i++)मानक लूप पैटर्न है जो वैसे भी हर सभ्य जावास्क्रिप्ट इंजन द्वारा अनुकूलित है।
बरगी

3
@FelixSanz: हाँ, और var i=0; i<a.length; i++सबसे अच्छा अभ्यास है।
बरगी

1
KISS । यदि आप लूप लिखते हैं, जहां आपको वास्तव में इसकी आवश्यकता है तो आप या तो कुछ गलत कर रहे हैं, या आपके पास "सर्वश्रेष्ठ अभ्यास" की तुलना में इसकी आवश्यकता के लिए बेहतर तर्क है। हां, यह एक मानक अभ्यास है, लेकिन सामान्य प्रदर्शन अनुकूलन के लिए नहीं, बल्कि केवल सूक्ष्म-अनुकूलन के लिए।
बर्गी

3
KISS हर जगह लागू होता है। समयपूर्व अनुकूलन एक विरोधी अभ्यास है।
बर्गी

7

जैसा कि दूसरों ने कहा है, आपको सरणी पर पुनरावृति करने के लिए for..in का उपयोग नहीं करना चाहिए।

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

यदि आप क्लीनर सिंटैक्स चाहते हैं, तो आप फॉरच का उपयोग कर सकते हैं:

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

यदि आप इस विधि का उपयोग करना चाहते हैं, तो सुनिश्चित करें कि आप पुराने ब्राउज़रों के लिए समर्थन जोड़ने के लिए ES5 शिम शामिल हैं।


2

उत्तर दिया गया है जल्दबाज़ी सही है लेकिन यह अधिक सुविधाजनक होगा

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

1

यहाँ एक समारोह है eachWithIndex जो कुछ भी चलने के साथ काम करता है।

आप एक समान फ़ंक्शन भी लिख सकते हैं 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)

जनरेटर के साथ अच्छी बात यह है कि वे आलसी हैं और तर्क के रूप में एक और जनरेटर का परिणाम ले सकते हैं।


1

यह एक समग्र पुनरावृत्ति का मेरा संस्करण है जो एक इंडेक्स और किसी भी पारित जनरेटर फ़ंक्शन के मूल्य को (धीमी) प्राइम इंटरव्यू के उदाहरण के साथ देता है:

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
}


आपके पास eachWithIndex[Symbol.iterator]केवल एक फ़ंक्शन के बजाय एक फ़ंक्शन क्यों हैeachWithIndex ? eachWithIndexपुनरावृत्ति इंटरफ़ेस को संतुष्ट नहीं करता है, जो पूरे बिंदु है Symbol.iterator
Ry-

@ Ry- अच्छी पकड़, eachWithIndexपुनरावृति को स्वीकार करने के लिए बदल गया और एक बंद समग्र पुनरावृत्ति को लौटाता है।
akurtser

1

बहुत अच्छे उत्तरों के शीर्ष पर सभी ने पोस्ट किया कि मैं जोड़ना चाहता हूं कि सबसे अच्छा प्रदर्शन समाधान ES6 है entries। यहां कई देवों के लिए यह गर्भनिरोधक लगता है, इसलिए मैंने यह परफैक्ट बेनक्रैम बनाया ।

यहां छवि विवरण दर्ज करें

यह ~ 6 गुना तेज है। मुख्य रूप से क्योंकि: ए) सरणी को एक से अधिक बार एक्सेस करने की आवश्यकता नहीं है और, बी) इंडेक्स कास्ट करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.