स्विफ्ट में सूचकांक और तत्व के साथ एक लूप को कैसे पुनरावृत्त करें


784

क्या कोई ऐसा फ़ंक्शन है जिसका उपयोग मैं किसी सरणी पर पुनरावृति करने के लिए कर सकता हूं और इसमें पायथन एन्युमरेट जैसे सूचकांक और तत्व दोनों हैं?

for index, element in enumerate(list):
    ...

जवाबों:


1659

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

for (index, element) in list.enumerated() {
  print("Item \(index): \(element)")
}

स्विफ्ट 3.0 से पहले और स्विफ्ट 2.0 से पहले, फ़ंक्शन को बुलाया गया था enumerate():

for (index, element) in list.enumerate() {
    print("Item \(index): \(element)")
}

स्विफ्ट 2.0 से पहले, enumerateएक वैश्विक समारोह था।

for (index, element) in enumerate(list) {
    println("Item \(index): \(element)")
}

3
हालाँकि यह स्विफ्ट 1.2 में एक टपल की तरह लगता है - 2.0 के बारे में निश्चित नहीं है - एन्यूमरेट एक एनुमरसिएंटेंस <आधार: सीक्वेंसटाइप> संरचना देता है।
१२:५१ पर १२

2
@ लेविथलॉन ध्यान देने योग्य या औसत दर्जे का प्रदर्शन ओवरहेड जो मायने रखेगा? नं।
डैन रोसेनस्टार्क

क्या सूचकांक को उपयोग करने का एकमात्र लाभ मिल रहा है enumerate?
हनी

29
शायद वे enumeratingस्विफ्ट 4 के लिए गेरुंड में बदल देंगे । रोमांचक!
दान रोसेनस्टार्क

3
@ for (index, element) inका उपयोग करते समय enumeratedभ्रामक है। होना चाहिएfor (offset, element) in
लियो डबस

115

स्विफ्ट 5 एक विधि कहा जाता है प्रदान करता है enumerated()के लिए Arrayenumerated()निम्नलिखित घोषणा है:

func enumerated() -> EnumeratedSequence<Array<Element>>

जोड़े का एक क्रम देता है (n, x), जहां n शून्य पर शुरू होने वाले एक पूर्णांक का प्रतिनिधित्व करता है और x अनुक्रम के एक तत्व का प्रतिनिधित्व करता है।


सरलतम मामलों में, आप enumerated()लूप के लिए उपयोग कर सकते हैं । उदाहरण के लिए:

let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
    print(index, ":", element)
}

/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/

ध्यान दें कि आप enumerated()लूप के साथ उपयोग करने के लिए सीमित नहीं हैं । वास्तव में, यदि आप enumerated()निम्न कोड के समान कुछ के लिए लूप के साथ उपयोग करने की योजना बना रहे हैं, तो आप इसे गलत कर रहे हैं:

let list = [Int](1...5)
var arrayOfTuples = [(Int, Int)]()

for (index, element) in list.enumerated() {
    arrayOfTuples += [(index, element)]
}

print(arrayOfTuples) // prints [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]

ऐसा करने का एक तेज़ तरीका है:

let list = [Int](1...5)
let arrayOfTuples = Array(list.enumerated())
print(arrayOfTuples) // prints [(offset: 0, element: 1), (offset: 1, element: 2), (offset: 2, element: 3), (offset: 3, element: 4), (offset: 4, element: 5)]

एक विकल्प के रूप में, आप इसके enumerated()साथ भी उपयोग कर सकते हैं map:

let list = [Int](1...5)
let arrayOfDictionaries = list.enumerated().map { (a, b) in return [a : b] }
print(arrayOfDictionaries) // prints [[0: 1], [1: 2], [2: 3], [3: 4], [4: 5]]

इसके अलावा, हालांकि इसकी कुछ सीमाएँ हैं , forEachलूप के लिए एक अच्छा प्रतिस्थापन हो सकता है:

let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }

/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/

का उपयोग करके enumerated()और makeIterator(), आप मैन्युअल रूप से अपने पर पुनरावृति कर सकते हैं Array। उदाहरण के लिए:

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    var generator = ["Car", "Bike", "Plane", "Boat"].enumerated().makeIterator()

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton(type: .system)
        button.setTitle("Tap", for: .normal)
        button.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
        button.addTarget(self, action: #selector(iterate(_:)), for: .touchUpInside)
        view.addSubview(button)
    }

    @objc func iterate(_ sender: UIButton) {
        let tuple = generator.next()
        print(String(describing: tuple))
    }

}

PlaygroundPage.current.liveView = ViewController()

/*
 Optional((offset: 0, element: "Car"))
 Optional((offset: 1, element: "Bike"))
 Optional((offset: 2, element: "Plane"))
 Optional((offset: 3, element: "Boat"))
 nil
 nil
 nil
 */

1
क्या सूचकांक को उपयोग करने का एकमात्र लाभ मिल रहा है enumerate?
हनी

52

स्विफ्ट 2 से शुरू करते हुए, एनुमुर्ट फ़ंक्शन को इस तरह संग्रह पर बुलाया जाना चाहिए:

for (index, element) in list.enumerate() {
    print("Item \(index): \(element)")
}

47

मैंने इसका जवाब एक शब्दकोश के साथ करने का तरीका ढूंढते हुए पाया , और यह पता चला कि इसे अनुकूलित करना काफी आसान है, बस तत्व के लिए एक टपल पास करें।

// Swift 2

var list = ["a": 1, "b": 2]

for (index, (letter, value)) in list.enumerate() {
    print("Item \(index): \(letter) \(value)")
}

18

आप बस वांछित परिणाम प्राप्त करने के लिए घनीभूत के लूप का उपयोग कर सकते हैं:

स्विफ्ट 2:

for (index, element) in elements.enumerate() {
    print("\(index): \(element)")
}

स्विफ्ट 3 और 4:

for (index, element) in elements.enumerated() {
    print("\(index): \(element)")
}

या आप बस एक ही परिणाम प्राप्त करने के लिए लूप के माध्यम से जा सकते हैं:

for index in 0..<elements.count {
    let element = elements[index]
    print("\(index): \(element)")
}

आशा है ये मदद करेगा।


14

आधारभूत गणना

for (index, element) in arrayOfValues.enumerate() {
// do something useful
}

या स्विफ्ट 3 के साथ ...

for (index, element) in arrayOfValues.enumerated() {
// do something useful
}

Enumerate, फ़िल्टर और मानचित्र

हालाँकि, मैं अक्सर मैप या फ़िल्टर के साथ संयोजन में enumerate का उपयोग करता हूं। उदाहरण के लिए, सरणियों के एक जोड़े पर संचालन के साथ।

इस सरणी में मैं विषम या अनुक्रमित तत्वों को फ़िल्टर करना चाहता था और उन्हें Ints से Doubles में परिवर्तित करता था। तो enumerate()आपको इंडेक्स और तत्व मिल जाता है, फिर फ़िल्टर इंडेक्स को चेक करता है, और अंत में परिणामी टपल से छुटकारा पाने के लिए मैं इसे केवल तत्व में मैप करता हूं।

let evens = arrayOfValues.enumerate().filter({
                            (index: Int, element: Int) -> Bool in
                            return index % 2 == 0
                        }).map({ (_: Int, element: Int) -> Double in
                            return Double(element)
                        })
let odds = arrayOfValues.enumerate().filter({
                            (index: Int, element: Int) -> Bool in
                            return index % 2 != 0
                        }).map({ (_: Int, element: Int) -> Double in
                            return Double(element)
                        })

9

.enumerate()कार्यों का उपयोग करना , लेकिन यह तत्व का सही सूचकांक प्रदान नहीं करता है; यह केवल 0 के साथ एक Int शुरुआत प्रदान करता है और प्रत्येक क्रमिक तत्व के लिए 1 से वृद्धि करता है। यह आमतौर पर अप्रासंगिक है, लेकिन ArraySliceप्रकार के साथ उपयोग किए जाने पर अप्रत्याशित व्यवहार की संभावना है । निम्नलिखित कोड लें:

let a = ["a", "b", "c", "d", "e"]
a.indices //=> 0..<5

let aSlice = a[1..<4] //=> ArraySlice with ["b", "c", "d"]
aSlice.indices //=> 1..<4

var test = [Int: String]()
for (index, element) in aSlice.enumerate() {
    test[index] = element
}
test //=> [0: "b", 1: "c", 2: "d"] // indices presented as 0..<3, but they are actually 1..<4
test[0] == aSlice[0] // ERROR: out of bounds

यह कुछ हद तक विरोधाभासी उदाहरण है, और यह व्यवहार में एक सामान्य मुद्दा नहीं है, लेकिन फिर भी मुझे लगता है कि यह जानने योग्य है कि यह हो सकता है।


2
it does not actually provide the true index of the element; it only provides an Int beginning with 0 and incrementing by 1 for each successive elementहां, इसीलिए इसे एन्यूमरेट कहा जाता है । इसके अलावा, स्लाइस सरणी नहीं है, इसलिए कोई आश्चर्य नहीं कि यह अलग तरह से व्यवहार करता है। यहां कोई बग नहीं है - सब कुछ डिजाइन द्वारा है। :)
एरिक आया

5
सच है, लेकिन मैंने इसे कभी बग नहीं कहा। यह सिर्फ संभावित रूप से अप्रत्याशित व्यवहार है जो मैंने सोचा था कि उन लोगों के लिए उल्लेख करने योग्य था जो नहीं जानते थे कि यह कैसे ArraySlice प्रकार के साथ नकारात्मक बातचीत कर सकता है।
कोल कैंपबेल

क्या आप वास्तविक तत्व का सूचकांक प्राप्त करने के किसी भी तरीके से अवगत हैं - उदाहरण के लिए यदि filterपहले का उपयोग कर रहे हैं ?
अलेक्जेंड्रे कैसगैन

9

स्विफ्ट 3 के साथ शुरू, यह है

for (index, element) in list.enumerated() {
  print("Item \(index): \(element)")
}

9

पूर्णता के लिए, आप अपने सरणी सूचकांकों पर आसानी से पुनरावृत्ति कर सकते हैं और संबंधित इंडेक्स पर तत्व तक पहुंचने के लिए सबस्क्रिप्ट का उपयोग कर सकते हैं:

let list = [100,200,300,400,500]
for index in list.indices {
    print("Element at:", index, " Value:", list[index])
}

ForEach का उपयोग करना

list.indices.forEach {
    print("Element at:", $0, " Value:", list[$0])
}

संग्रह enumerated()विधि का उपयोग करना । ध्यान दें कि यह offsetऔर के साथ tuples का एक संग्रह लौटाता है element:

for item in list.enumerated() {
    print("Element at:", item.offset, " Value:", item.element)
}

forEach का उपयोग करना:

list.enumerated().forEach {
    print("Element at:", $0.offset, " Value:", $0.element)
}

जो छपेंगे

तत्व पर: 0 मान: 100

तत्व पर: 1 मान: 200

तत्व पर: 2 मान: 300

पर तत्व: 3 मूल्य: 400

पर तत्व: 4 मूल्य: 500

यदि आपको सरणी सूचकांक (ऑफ़सेट नहीं) की आवश्यकता है और इसका तत्व आप संग्रह को बढ़ा सकते हैं और अनुक्रमित तत्वों को प्राप्त करने के लिए अपनी खुद की विधि बना सकते हैं:

extension Collection {
    func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
        var index = startIndex
        for element in self {
            try body((index,element))
            formIndex(after: &index)
        }
    }
}

एलेक्स द्वारा सुझाया गया एक अन्य संभावित कार्यान्वयन अपने तत्वों के साथ संग्रह सूचकांकों को ज़िप करना है:

extension Collection {
    func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
        for element in zip(indices, self) { try body(element) }
    }
}

परिक्षण:

let list =  ["100","200","300","400","500"]
list.dropFirst(2).indexedElements {
    print("Index:", $0.index, "Element:", $0.element)
}

यह p [rint होगा

सूचकांक: 2 तत्व: 300

सूचकांक: 3 तत्व: 400

सूचकांक: 4 तत्व: 500


BTW आप लागू कर सकते हैं enumeratedIndicesके साथ खत्म हो गया पाशन द्वाराzip(self.indices, self)
को पुनः स्थापित मोनिका - अलेक्जेंडर

@ अलेक्जेंडर-रिंस्टोमोनिका for element in zip(indices, self) { try body(element) }। Btw मुझे पसंद नहीं है कि मैंने जो नामकरण चुना है, indexedElementsवह बेहतर बताता है कि यह क्या करता है
लियो डबस

Ooo मुझे लगता है कि यह एक बेहतर नाम है। हाँ, एक forलूप काम करता है, लेकिन यह भीzip(self.indices, self) .forEach(body)
अलेक्जेंडर - मोनिका

@ अलेक्जेंडर-रिंस्टोमोनिका forEachपर्दे के पीछे लूप के लिए करता है। मैं इसे सरल रखना पसंद करता हूं github.com/apple/swift/blob/master/stdlib/public/core/… @inlinable public func forEach( _ body: (Element) throws -> Void ) rethrows { for element in self { try body(element) } } }
सिंह दबस

7

यह एन्यूमरेशन के लूप का सूत्र है:

for (index, value) in shoppingList.enumerate() {
print("Item \(index + 1): \(value)")
}

अधिक विवरण के लिए आप यहां देख सकते हैं ।


5

मैं व्यक्तिगत रूप से forEachविधि का उपयोग करना पसंद करता हूं :

list.enumerated().forEach { (index, element) in
    ...
}

आप लघु संस्करण का भी उपयोग कर सकते हैं:

list.enumerated().forEach { print("index: \($0.0), value: \($0.1)") }

4

Xcode 8 और स्विफ्ट 3: ऐरे का उपयोग करके एनुमरेट किया जा सकता है tempArray.enumerated()

उदाहरण:

var someStrs = [String]()

someStrs.append("Apple")  
someStrs.append("Amazon")  
someStrs += ["Google"]    


for (index, item) in someStrs.enumerated()  
{  
        print("Value at index = \(index) is \(item)").  
}

कंसोल:

Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google

3

उन लोगों के लिए जो उपयोग करना चाहते हैं forEach

स्विफ्ट 4

extension Array {
  func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
    try zip((startIndex ..< endIndex), self).forEach(body)
  }
}

या

array.enumerated().forEach { ... }

2

आप जो करना चाहते हैं, उसके लिए आपको इसका उपयोग करना चाहिए enumerated() अपने ऐरे पर विधि का :

for (index, element) in list.enumerated() {
    print("\(index) - \(element)")
}

-1

हमने इसे लागू करने के लिए एन्यूमरेट फ़ंक्शन कहा है। पसंद

के लिए (सूचकांक, तत्व) array.enumerate () {

// सूचकांक सरणी का सूचकांक है

// तत्व सरणी का तत्व है

}

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