Swift में ऐरे को iterate करते समय इंडेक्स कैसे पाएं? लोकप्रिय सवाल का जवाब
\n\nकल्पना करें: आप Swift में कोड लिख रहे हैं और चाहते हैं कि ऐरे के हर एलिमेंट के साथ उसकी पोजीशन (इंडेक्स) भी पता हो। चाहे आपको इंडेक्स के हिसाब से एलिमेंट बदलने हों, पड़ोसी वैल्यूज की तुलना करनी हो, या सिर्फ एक नंबर वाली लिस्ट प्रिंट करनी हो — सवाल एक ही है। Stack Overflow पर "How to iterate a loop with index and element in Swift" ने हज़ारों व्यूज बटोरे हैं। यानी यह टॉपिक कई डेवलपर्स को परेशान करता है।
\n\nइस आर्टिकल में हम सिर्फ एक रेडीमेड जवाब नहीं देंगे। हम गहराई में जाएंगे: कौन से तरीके मौजूद हैं, कौन सा तेज़ है, कौन सा ज़्यादा सुरक्षित है, और क्यों enumerated() डी-फैक्टो स्टैंडर्ड बन गया है। चलिए शुरू करते हैं!
समस्या: सिर्फ for-in क्यों काफी नहीं है?
\n\nमान लीजिए आपके पास स्ट्रिंग्स का एक ऐरे है:
\n\nlet fruits = ["सेब", "केला", "चेरी", "खरबूजा"]\n\nसबसे आसान तरीका है for-in:
for fruit in fruits {\n print(fruit)\n}\n\nइससे फलों के नाम प्रिंट होंगे। लेकिन अगर इंडेक्स भी चाहिए? जैसे: "1. सेब, 2. केला..."? साधारण for-in इंडेक्स नहीं देता। तब हमें जुगाड़ करना पड़ता है:
var index = 0\nfor fruit in fruits {\n print("\\(index). \\(fruit)")\n index += 1\n}\n\nकाम करता है? हाँ। सुंदर है? नहीं। और अगर ऐरे खाली हो? या अगर आप गलती से index बढ़ाना भूल जाएं? बग्स की दुनिया में आपका स्वागत है। Swift इसके लिए ज़्यादा स्मार्ट तरीके देता है।
तरीका #1: क्लासिक — enumerated() मेथड
\n\nयह सबसे लोकप्रिय और सुझाया गया तरीका है। enumerated() मेथड टपल्स (offset: Int, element: Element) का एक सीक्वेंस लौटाता है। देखते हैं यह कैसे काम करता है:
for (index, fruit) in fruits.enumerated() {\n print("\\(index + 1). \\(fruit)")\n}\n\nआउटपुट:
\n1. सेब\n2. केला\n3. चेरी\n4. खरबूजा\n\nअंदर क्या हो रहा है?
\n\nenumerated() कोई नया ऐरे नहीं बनाता। यह EnumeratedSequence टाइप का एक लेज़ी सीक्वेंस लौटाता है। इसका मतलब है कि एलिमेंट्स किसी नई डेटा स्ट्रक्चर में कॉपी नहीं होते — वे चलते-फिरते "रैप" हो जाते हैं। हर बार जब आप अगला एलिमेंट एक्सेस करते हैं, सीक्वेंस बस काउंटर बढ़ाकर टपल लौटा देता है। यह मेमोरी के लिहाज से बहुत कुशल है, खासकर बड़ी कलेक्शन के लिए।
एक ज़रूरी बात: offset हमेशा 0 से शुरू होता है। अगर आपको 1 से इंडेक्स चाहिए (जैसे लिस्ट नंबरिंग में), तो बस एक जोड़ दें। Swift यह अपने आप नहीं करता — यह भाषा डिज़ाइनरों का जानबूझकर लिया गया फैसला है, ताकि ऐरे इंडेक्सिंग के साथ एकरूपता बनी रहे।
forEach के साथ enumerated()
\n\nforEach मेथड भी enumerated() को सपोर्ट करता है:
fruits.enumerated().forEach { (index, fruit) in\n print("\\(index). \\(fruit)")\n}\n\nfor-in और forEach के बीच एक अहम अंतर है: forEach के अंदर break या continue का इस्तेमाल नहीं किया जा सकता। अगर लूप को बीच में रोकना है — तो for-in का उपयोग करें।
तरीका #2: रेंज (Range) के ज़रिए इंडेक्सिंग
\n\nपुराना, लेकिन अब भी दिखने वाला तरीका — इंडेक्स पर लगातार iterate करना:
\n\nfor index in 0..<fruits.count {\n print("\\(index). \\(fruits[index])")\n}\n\nदेखने में आसान लगता है। लेकिन इसमें कुछ खतरे हैं:
\n\n- \n
- सुरक्षा: अगर लूप के दौरान ऐरे बदल जाए (जैसे मल्टीथ्रेडेड कोड में), तो
fruits.countपुराना हो सकता है और आप ऐरे की सीमा से बाहर निकल सकते हैं। \n - पढ़ने में आसानी: कोड ज़्यादा "लो-लेवल" लगता है। दूसरे डेवलपर्स को यह समझने में एक पल और लगेगा कि आप क्या कर रहे हैं। \n
- परफॉरमेंस: इंडेक्स से एक्सेस
fruits[index]ऐरे के लिए O(1) ऑपरेशन है, लेकिन दूसरी कलेक्शन के लिए