मैं एक स्विफ्ट एनम की गिनती कैसे प्राप्त करूं?


186

मैं स्विफ्ट एनम में मामलों की संख्या कैसे निर्धारित कर सकता हूं?

(मैं सभी मूल्यों के माध्यम से मैन्युअल रूप से गणना करने से बचना चाहूंगा , या यदि संभव हो तो पुरानी " enum_count चाल " का उपयोग कर सकता हूं ।)

जवाबों:


173

स्विफ्ट 4.2 (एक्सकोड 10) के रूप में आप CaseIterableप्रोटोकॉल के अनुरूप घोषित कर सकते हैं , यह संबद्ध मूल्यों के बिना सभी गणना के लिए काम करता है:

enum Stuff: CaseIterable {
    case first
    case second
    case third
    case forth
}

मामलों की संख्या अब बस के साथ प्राप्त की है

print(Stuff.allCases.count) // 4

अधिक जानकारी के लिए देखें


1
स्विफ्ट के नवीनतम संस्करण में, इसकी थ्रोइंग एरर "टाइप 'डीएएफएफएल" प्रोटोकॉल' रावरेपरेसेन्टेबल 'के अनुरूप नहीं है। क्यों यह मेरे लिए मजबूर कर रहा है कि पालन करने के लिए? कोई उपाय?
सत्यम

@ सत्यम: डीएएफएफएल क्या है?
मार्टिन आर

खेद है कि मैं यह उल्लेख करना भूल गया कि "डीएएफएफएलओएल" एक सरल शब्द है जो किसी भी अन्य प्रोटोकॉल से विरासत में नहीं मिलता है।
सत्यम

1
यह सबसे अच्छा समाधान है, लेकिन सिर्फ स्पष्टता के लिए - ऐप्पल डेवलपर्स केवल Xcode 10 (और इसलिए स्विफ्ट 4.2) एक बार बीटा से बाहर आ जाते हैं (इसलिए 14 सितंबर 2018 के आसपास होने की संभावना है)।
जोसफ

1
@DaniSpringer: आप पर रक्तमय विवरण मिलेगा github.com/apple/swift-evolution/blob/master/proposals/... । लेकिन आमतौर पर आपको कंपाइलर के ऑटोमैटिक टाइप इंट्रैक्शन की वजह से उस प्रकार की जरूरत नहीं होती है।
मार्टिन आर

143

मेरे पास एक ब्लॉग पोस्ट है जो इस पर अधिक विस्तार से जाती है, लेकिन जब तक आपके एनम का कच्चा प्रकार एक पूर्णांक है, तब तक आप इस तरह से एक गणना जोड़ सकते हैं:

enum Reindeer: Int {
    case Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen
    case Rudolph

    static let count: Int = {
        var max: Int = 0
        while let _ = Reindeer(rawValue: max) { max += 1 }
        return max
    }()
}

16
हालांकि अच्छा है क्योंकि आपको किसी मूल्य को हार्डकोड करने की आवश्यकता नहीं है, यह हर बार जब यह कहा जाता है, तो हर एनम मूल्य को तुरंत कर देगा। O (1) के बजाय O (n) है। :(
कोड कमांडर

4
यह सन्निहित Int के लिए एक अच्छा समाधान है। मैं एक मामूली संशोधन पसंद करते हैं। स्टैटिक काउंट प्रॉपर्टी को स्टैटिक मेथड काउंटेस () में बदल दें और इसे स्टैटिक कंटिन्यू केसकाउंट में असाइन करें जो आलसी है और बार-बार कॉल के साथ परफॉर्मेंस को बेहतर बनाता है।
टॉम पेलाया जूल

2
@ शम्सअहमद: गणना किए गए संस्करण को एक स्थिर में परिवर्तित कर दिया।
नैट कुक

3
क्या होगा यदि आप एनम में कुछ मूल्य याद करते हैं? जैसे case A=1, B=3?
सेशो

2
वहाँ 2 मान्यताओं के अलावा हैं enumएक होने Intस्विफ्ट enum के इंट कच्चे मूल्यों के साथ 0 (भले ही है कि डिफ़ॉल्ट व्यवहार) और उनके कच्चे मूल्यों से शुरू करने के लिए मनमाने ढंग से किया जा सकता है की जरूरत नहीं है, वे की जरूरत नहीं है: कच्चे मूल्य है कि आप उल्लेख करना भूल गया 1 से वेतन वृद्धि (भले ही वह डिफ़ॉल्ट व्यवहार हो)।
दाविद पास्ज़टोर

90

Xcode 10 अपडेट

अपनाने CaseIterableenum में प्रोटोकॉल, तो वह एक स्थिर प्रदान करता है allCasesसंपत्ति है जो एक के रूप में सभी enum मामलों में शामिल है Collection। बस इसका उपयोग करेंcountएनुम के कितने मामले हैं, यह जानने के लिए संपत्ति ।

उदाहरण के लिए मार्टिन का उत्तर देखें (और मेरे बजाय उसके जवाबों को आगे बढ़ाएं)


चेतावनी : नीचे दी गई विधि अब काम नहीं करती है।

मैं किसी भी सामान्य विधि के बारे में पता नहीं कर रहा हूँ कि एनम मामलों की संख्या की गणना करें। हालांकि मैंने देखा है कि hashValueएनम मामलों की संपत्ति में वृद्धि होती है, जो शून्य से शुरू होती है, और उस क्रम से निर्धारित होती है जिसमें मामलों को घोषित किया जाता है। तो, अंतिम ईनम प्लस का हैश मामलों की संख्या से मेल खाता है।

इस एनम के साथ उदाहरण के लिए:

enum Test {
    case ONE
    case TWO
    case THREE
    case FOUR

    static var count: Int { return Test.FOUR.hashValue + 1}
}

count रिटर्न 4।

मैं यह नहीं कह सकता कि यदि यह नियम है या भविष्य में यह कभी बदलेगा, तो अपने जोखिम पर उपयोग करें :)


48
निर्विवाद सुविधा से जीना, अनिर्दिष्ट सुविधा से मरना। मुझें यह पसंद है!
नैट कुक

9
हमें वास्तव में hashValuesइन चीजों पर निर्भर नहीं होना चाहिए ; हम सभी जानते हैं कि यह कुछ यादृच्छिक अद्वितीय मूल्य है - कुछ संकलक कार्यान्वयन विवरण के आधार पर भविष्य में बहुत आसानी से बदल सकते हैं; लेकिन कुल मिलाकर, अंतर्निहित गिनती कार्यक्षमता की कमी परेशान करती है।
जोरावर

16
आप स्पष्ट रूप से स्थापित करने के कोई आपत्ति नहीं है case ONE = 0, तो आप बदल सकते हैं hashValueके साथ rawValue
केविन क्यूई

3
यहां चिंता हैशवैल्यू की एक अनिर्धारित संपत्ति का उपयोग, इसलिए मेरा सुझाव कच्चे माल की एक प्रलेखित संपत्ति का उपयोग करना है।
केविन क्यूई

7
आपने पहले से ही इस तथ्य को हार्डकोड किया है कि निरंतर सबसे अधिक मूल्य है, static var count = 4स्विफ्ट के भविष्य के कार्यान्वयन के भाग्य में अपने भाग्य को छोड़ने के बजाय सिर्फ कुछ का उपयोग करने के लिए बेहतर और सुरक्षित है
डेल

72

मैं एक पुन: प्रयोज्य प्रोटोकॉल को परिभाषित करता हूं जो नैट कुक द्वारा पोस्ट किए गए दृष्टिकोण के आधार पर स्वचालित रूप से केस काउंट करता है।

protocol CaseCountable {
    static var caseCount: Int { get }
}

extension CaseCountable where Self: RawRepresentable, Self.RawValue == Int {
    internal static var caseCount: Int {
        var count = 0
        while let _ = Self(rawValue: count) {
            count += 1
        }
        return count
    }
}

फिर मैं उदाहरण के लिए इस प्रोटोकॉल का पुन: उपयोग कर सकता हूं:

enum Planet : Int, CaseCountable {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//..
print(Planet.caseCount)

1
अच्छा और सुरुचिपूर्ण, स्वीकृत उत्तर होना चाहिए IMHO
शन्नोगा

1
शायद यह परिवर्तन करने के लिए बेहतर है count++के लिए count+=1के बाद से ++अंकन स्विफ्ट 3 में निकाल दिया जाएगा
अलादीन

1
केवल उसी के साथ नहीं किया जा सकता है static var caseCount: Int { get }? क्यों की जरूरत है static func?
pxpgraphics

क्या होगा यदि आप एनम में कुछ मूल्य याद करते हैं? जैसे case A=1, B=3?
साशो

1
@ साशो, तो यह काम नहीं करेगा। इसके लिए आपके मामलों को शुरू करने 0और कोई अंतराल नहीं है।
एनआरआईटीएच

35

जैसा कि इस उत्तर में दिखाया गया है, स्थिर allValues ​​सरणी बनाएँ

enum ProductCategory : String {
     case Washers = "washers", Dryers = "dryers", Toasters = "toasters"

     static let allValues = [Washers, Dryers, Toasters]
}

...

let count = ProductCategory.allValues.count

यह तब भी मददगार होता है जब आप मूल्यों की गणना करना चाहते हैं, और सभी Enum प्रकारों के लिए काम करते हैं


यद्यपि एक्सटेंशन समाधान और बहुत मैनुअल के रूप में सुरुचिपूर्ण नहीं है, मेरा मानना ​​है कि यह सबसे उपयोगी है क्योंकि यह गिनती से बहुत अधिक प्रदान करता है। यह आपको मूल्यों का क्रम और सभी मूल्यों की एक सूची देता है।
नादर एलोशेकर

2
आप गणना करके गणना को एनुम में भी जोड़ सकते हैं static let count = allValues.count । फिर आप allValuesचाहें तो निजी बना सकते हैं ।
थॉमस डब्ल्यू

15

यदि पूर्णांक एनमों का उपयोग करने के खिलाफ कार्यान्वयन में कुछ भी नहीं है, तो आप एनम Countमें सदस्यों की संख्या का प्रतिनिधित्व करने के लिए बुलाया एक अतिरिक्त सदस्य मूल्य जोड़ सकते हैं - नीचे उदाहरण देखें:

enum TableViewSections : Int {
  case Watchlist
  case AddButton
  case Count
}

अब आप कॉल करके enum में सदस्यों की संख्या प्राप्त कर सकते हैं, TableViewSections.Count.rawValue जो ऊपर दिए गए उदाहरण के लिए 2 लौटाएगा।

जब आप एक स्विच स्टेटमेंट में एनम को संभाल रहे हैं, तो उस Countसदस्य का सामना करते समय एक जोरदार विफलता फेंकना सुनिश्चित करें जहां आप इसकी उम्मीद नहीं करते हैं:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let currentSection: TableViewSections = TableViewSections.init(rawValue:section)!
  switch(currentSection) {
  case .Watchlist:
    return watchlist.count
  case .AddButton:
    return 1
  case .Count:
    assert(false, "Invalid table view section!")
  }
}

मैं उस समाधान को पसंद करता हूं क्योंकि अधिक गणना मूल्यों को जोड़ते समय यह स्वचालित रूप से गणना को बदल देता है। हालांकि यह ध्यान रखें कि यह केवल तभी काम करता है जब एनम के कच्चे माल की शुरुआत 0.
जोर्न

2
सहमत हों, दो प्रतिबंध हैं: पूर्णांक एनम होना चाहिए और शून्य से शुरू होना चाहिए और वृद्धि जारी रखना चाहिए।
ज़ोरयूर

3
मुझे लगा कि स्विफ्ट के अधिक शक्तिशाली एनम का पूरा बिंदु यह था कि हमें उसी हैक का उपयोग नहीं करना होगा जिसका उपयोग हमने Objective-C: /
pkamb

14

इस तरह का फंक्शन आपके एनम की गिनती लौटाने में सक्षम है।

स्विफ्ट 2 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(&i) { UnsafePointer<T>($0).memory }).hashValue != 0 {
        i += 1
    }
    return i
}

स्विफ्ट 3 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
   var i = 1
   while (withUnsafePointer(to: &i, {
      return $0.withMemoryRebound(to: T.self, capacity: 1, { return $0.pointee })
   }).hashValue != 0) {
      i += 1
   }
      return i
   }

3
यह अब स्विफ्ट के लिए काम नहीं करता है। 3. उचित कार्यान्वयन के लिए काम करने की कोशिश कर रहा है, लेकिन खाली आ रहा है
कोडी विंटन

इस डिबग करने के लिए बहुत unfun हो जाएगा स्मृति पते के तुरंत के अंत करने के लिए आसन्न अगर enumहै भी Hashable एक ही प्रकार के।
एनआरआईटीएच

10

इंडेक्स के साथ स्ट्रिंग एनम

enum eEventTabType : String {
    case Search     = "SEARCH"
    case Inbox      = "INBOX"
    case Accepted   = "ACCEPTED"
    case Saved      = "SAVED"
    case Declined   = "DECLINED"
    case Organized  = "ORGANIZED"

    static let allValues = [Search, Inbox, Accepted, Saved, Declined, Organized]
    var index : Int {
       return eEventTabType.allValues.indexOf(self)!
    }
}

गणना: eEventTabType.allValues.count

सूचकांक: objeEventTabType.index

का आनंद लें :)


10

ओह हे सब लोग, यूनिट परीक्षणों के बारे में क्या?

func testEnumCountIsEqualToNumberOfItemsInEnum() {

    var max: Int = 0
    while let _ = Test(rawValue: max) { max += 1 }

    XCTAssert(max == Test.count)
}

यह एंटोनियो के समाधान के साथ संयुक्त है:

enum Test {

    case one
    case two
    case three
    case four

    static var count: Int { return Test.four.hashValue + 1}
}

मुख्य कोड में आपको O (1) प्लस मिलता है, यदि आपको कोई फेल होने वाला टेस्ट मिलता है, तो कोई एनुम केस जोड़ता है fiveऔर कार्यान्वयन को अपडेट नहीं करता है count


7

यह फ़ंक्शन 2 अनिर्धारित वर्तमान (स्विफ्ट 1.1) enumव्यवहार पर निर्भर करता है:

  • का मेमोरी लेआउट enumसिर्फ एक सूचकांक है case। यदि केस संख्या 2 से 256 तक है, तो यह है UInt8
  • यदि अमान्य केस इंडेक्स enumसे बिट-कास्ट किया गया है , तो यह हैhashValue0

तो अपने जोखिम पर उपयोग करें :)

func enumCaseCount<T:Hashable>(t:T.Type) -> Int {
    switch sizeof(t) {
    case 0:
        return 1
    case 1:
        for i in 2..<256 {
            if unsafeBitCast(UInt8(i), t).hashValue == 0 {
                return i
            }
        }
        return 256
    case 2:
        for i in 257..<65536 {
            if unsafeBitCast(UInt16(i), t).hashValue == 0 {
                return i
            }
        }
        return 65536
    default:
        fatalError("too many")
    }
}

उपयोग:

enum Foo:String {
    case C000 = "foo"
    case C001 = "bar"
    case C002 = "baz"
}
enumCaseCount(Foo) // -> 3

रिलीज और एडहॉक एप्लिकेशन में CRASH
HotJard

यह सिम्युलेटर में काम करता है लेकिन वास्तविक 64 बिट डिवाइस पर नहीं।
डैनियल नॉर्ड

5

मैंने एक साधारण एक्सटेंशन लिखा है जो सभी एनमों को देता है जहां कच्चा मूल्य एक countसंपत्ति है:

extension RawRepresentable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

दुर्भाग्य से यह उस countसंपत्ति को देता है OptionSetTypeजहां यह ठीक से काम नहीं करेगा, इसलिए यहां एक और संस्करण है जिसे CaseCountableकिसी भी एनम के लिए प्रोटोकॉल के लिए स्पष्ट अनुरूपता की आवश्यकता होती है जिसे आप गिनना चाहते हैं:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

यह टॉम पेलिया द्वारा पोस्ट किए गए दृष्टिकोण के समान है, लेकिन सभी पूर्णांक प्रकारों के साथ काम करता है।


4

बेशक, यह गतिशील नहीं है, लेकिन कई उपयोगों के लिए आप अपने Enum में जोड़े गए स्थिर संस्करण के साथ प्राप्त कर सकते हैं

static var count: Int{ return 7 }

और फिर इसका उपयोग करें EnumName.count


3
enum EnumNameType: Int {
    case first
    case second
    case third

    static var count: Int { return EnumNameType.third.rawValue + 1 }
}

print(EnumNameType.count) //3

या

enum EnumNameType: Int {
    case first
    case second
    case third
    case count
}

print(EnumNameType.count.rawValue) //3

* स्विफ्ट 4.2 पर (Xcode 10) उपयोग कर सकते हैं:

enum EnumNameType: CaseIterable {
    case first
    case second
    case third
}

print(EnumNameType.allCases.count) //3

2

मेरे उपयोग के मामले के लिए, एक कोडबेस में जहां कई लोग एक enum में चाबियाँ जोड़ सकते हैं, और ये सभी मामले allKeys संपत्ति में उपलब्ध होने चाहिए, यह महत्वपूर्ण है कि सभीKeyum में कुंजियों के विरुद्ध मान्य किया जाए। यह किसी को सभी कुंजी सूची में अपनी कुंजी जोड़ने के लिए भूल जाने से बचने के लिए है।एलुम में कुंजियों की संख्या के खिलाफ allKeys सरणी की गिनती (पहली बार डुप्स से बचने के लिए एक सेट के रूप में बनाई गई) से मेल खाते हुए सुनिश्चित करता है कि वे सभी मौजूद हैं।

ऊपर दिए गए कुछ उत्तर स्विफ्ट 2 में इसे प्राप्त करने का तरीका दिखाते हैं लेकिन स्विफ्ट 3 में कोई भी काम नहीं करता है । यहाँ स्विफ्ट 3 स्वरूपित संस्करण है:

static func enumCount<T: Hashable>(_ t: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(to: &i) {
      $0.withMemoryRebound(to:t.self, capacity:1) { $0.pointee.hashValue != 0 }
    }) {
      i += 1
    }
    return i
}

static var allKeys: [YourEnumTypeHere] {
    var enumSize = enumCount(YourEnumTypeHere.self)

    let keys: Set<YourEnumTypeHere> = [.all, .your, .cases, .here]
    guard keys.count == enumSize else {
       fatalError("Missmatch between allKeys(\(keys.count)) and actual keys(\(enumSize)) in enum.")
    }
    return Array(keys)
}

आपके उपयोग के मामले के आधार पर, आप प्रत्येक अनुरोध पर allKeys का उपयोग करने के ओवरहेड से बचने के लिए विकास में परीक्षण चलाना चाहते हैं।


2

आप इसे इतना जटिल क्यों बनाते हैं? Int enum के SIMPLEST काउंटर को जोड़ना है:

case Count

अंततः। और ... वायोला - अब आपके पास गिनती है - तेज और सरल


1
यह क) एक विलक्षण एनुम केस जोड़ता है और बी) काम नहीं करेगा यदि एनुम का कच्चा प्रकार इंट के अलावा कुछ भी हो।
रॉबर्ट एटकिन्स

यह वास्तव में एक बुरा जवाब नहीं है। जैसा कि @Tom Pelaia के उत्तर के ऊपर है, हालांकि, इसे शुरू करने के लिए कच्चे मानों की आवश्यकता होती है 0और अनुक्रम में कोई अंतराल नहीं होता है।
NRitH

1

यदि आप अंतिम एनम में अपने कोड को आधार नहीं बनाना चाहते हैं तो आप अपने एनम के अंदर यह फ़ंक्शन बना सकते हैं।

func getNumberOfItems() -> Int {
    var i:Int = 0
    var exit:Bool = false
    while !exit {
        if let menuIndex = MenuIndex(rawValue: i) {
            i++
        }else{
            exit = true
        }
    }
    return i
}

1

एक स्विफ्ट 3 संस्करण Intप्रकार के साथ काम कर रहा है :

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue == Int {
    static var count: RawValue {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) { i += 1 }
        return i
    }
}

क्रेडिट: बज़ और नैट कुक के उत्तरों के आधार पर।

जेनेरिक IntegerType(स्विफ्ट 3 का नाम बदला हुआ Integer) समर्थित नहीं है, क्योंकि यह एक भारी खंडित सामान्य प्रकार है जिसमें बहुत सारे कार्यों का अभाव है। successorअब स्विफ्ट 3 के साथ उपलब्ध नहीं है।

ज्ञात हो कि कोड कमांडर से लेकर नैट कुक के उत्तर तक की टिप्पणी अभी भी मान्य है:

हालांकि अच्छा है क्योंकि आपको किसी मूल्य को हार्डकोड करने की आवश्यकता नहीं है, यह हर बार जब यह कहा जाता है, तो हर एनम मूल्य को तुरंत कर देगा। O (1) के बजाय O (n) है।

जहां तक ​​मुझे पता है कि वर्तमान में प्रोटोकॉल एक्सटेंशन के रूप में उपयोग करने पर कोई वर्कअराउंड नहीं है (और नैट कुक की तरह प्रत्येक एनम में लागू नहीं किया गया) स्थैतिक संग्रहीत गुणों के कारण जेनेरिक प्रकारों में समर्थित नहीं है।

वैसे भी, छोटी दुश्मनी के लिए यह कोई मुद्दा नहीं होना चाहिए। एक सामान्य उपयोग का मामला पहले से ही ज़ॉएर द्वारा उल्लिखित के section.countलिए होगा UITableViews


1

Matthieu Riegler उत्तर का विस्तार करते हुए, यह Swift 3 के लिए एक समाधान है जिसमें जेनेरिक के उपयोग की आवश्यकता नहीं है, और इसे आसानी से enum प्रकार का उपयोग करके बुलाया जा सकता है EnumType.elementsCount:

extension RawRepresentable where Self: Hashable {

    // Returns the number of elements in a RawRepresentable data structure
    static var elementsCount: Int {
        var i = 1
        while (withUnsafePointer(to: &i, {
            return $0.withMemoryRebound(to: self, capacity: 1, { return 
                   $0.pointee })
        }).hashValue != 0) {
            i += 1
        }
        return i
}

0

मैंने एक प्रोटोकॉल (EnumIntArray) और एक वैश्विक उपयोगिता फ़ंक्शन (enumIntArray) बनाकर अपने लिए इस समस्या को हल किया, जो किसी भी एनम (स्विफ्ट 1.2 का उपयोग करके "ऑल" वैरिएबल को जोड़ना बहुत आसान बनाता है। "सभी" चर में सभी तत्वों की एक सरणी समाहित होगी ताकि आप गणना के लिए all.count का उपयोग कर सकें

यह केवल उन एनमों के साथ काम करता है जो Int के कच्चे मूल्यों का उपयोग करते हैं लेकिन शायद यह अन्य प्रकारों के लिए कुछ प्रेरणा प्रदान कर सकता है।

यह "गैप इन नंबरिंग" और "अत्यधिक समय को पुनरावृति करने" के लिए संबोधित करता है।

अपने Enum में EnumIntArray प्रोटोकॉल को जोड़ने और उसके बाद enumIntArray फ़ंक्शन को कॉल करके "सब" स्टैटिक वैरिएबल को परिभाषित करने और इसे पहले तत्व (और अगर नंबरिंग में अंतराल हैं तो आखिरी) प्रदान करने पर विचार करना है।

क्योंकि स्टेटिक वैरिएबल केवल एक बार इनिशियलाइज़ होता है, सभी कच्चे मूल्यों से गुजरने का ओवरहेड केवल एक बार आपके प्रोग्राम को हिट करता है।

उदाहरण (अंतराल के बिना):

enum Animals:Int, EnumIntArray
{ 
  case Cat=1, Dog, Rabbit, Chicken, Cow
  static var all = enumIntArray(Animals.Cat)
}

उदाहरण (अंतराल के साथ):

enum Animals:Int, EnumIntArray
{ 
  case Cat    = 1,  Dog, 
  case Rabbit = 10, Chicken, Cow
  static var all = enumIntArray(Animals.Cat, Animals.Cow)
}

यहाँ वह कोड है जो इसे लागू करता है:

protocol EnumIntArray
{
   init?(rawValue:Int)
   var rawValue:Int { get }
}

func enumIntArray<T:EnumIntArray>(firstValue:T, _ lastValue:T? = nil) -> [T]
{
   var result:[T] = []
   var rawValue   = firstValue.rawValue
   while true
   { 
     if let enumValue = T(rawValue:rawValue++) 
     { result.append(enumValue) }
     else if lastValue == nil                     
     { break }

     if lastValue != nil
     && rawValue  >  lastValue!.rawValue          
     { break }
   } 
   return result   
}

0

या आप बस एनम के _countबाहर परिभाषित कर सकते हैं , और इसे सांख्यिकीय रूप से संलग्न कर सकते हैं:

let _count: Int = {
    var max: Int = 0
    while let _ = EnumName(rawValue: max) { max += 1 }
    return max
}()

enum EnumName: Int {
    case val0 = 0
    case val1
    static let count = _count
}

इस तरह से आप चाहे जितनी भी पहेली बना लें, यह केवल एक बार ही बनेगी।

(यदि staticऐसा हो तो इस उत्तर को हटा दें )


0

निम्नलिखित विधि CoreKit से आती है और कुछ अन्य लोगों द्वारा सुझाए गए उत्तरों के समान है। यह स्विफ्ट 4 के साथ काम करता है।

public protocol EnumCollection: Hashable {
    static func cases() -> AnySequence<Self>
    static var allValues: [Self] { get }
}

public extension EnumCollection {

    public static func cases() -> AnySequence<Self> {
        return AnySequence { () -> AnyIterator<Self> in
            var raw = 0
            return AnyIterator {
                let current: Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: self, capacity: 1) { $0.pointee } }
                guard current.hashValue == raw else {
                    return nil
                }
                raw += 1
                return current
            }
        }
    }

    public static var allValues: [Self] {
        return Array(self.cases())
    }
}

enum Weekdays: String, EnumCollection {
    case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}

फिर आपको बस कॉल करने की जरूरत है Weekdays.allValues.count


0
enum WeekDays : String , CaseIterable
{
  case monday = "Mon"
  case tuesday = "Tue"
  case wednesday = "Wed"
  case thursday = "Thu"
  case friday = "Fri"
  case saturday = "Sat"
  case sunday = "Sun"
}

var weekdays = WeekDays.AllCases()

print("\(weekdays.count)")

-1
struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }
            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().enumCount
    }
}

enum E {
    case A
    case B
    case C
}

E.enumCases() // [A, B, C]
E.enumCount   //  3

लेकिन गैर-एनम प्रकारों पर उपयोग के साथ सावधान रहें। कुछ समाधान हो सकता है:

struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            guard sizeof(T) == 1 else {
                return nil
            }
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }

            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().count
    }
}

enum E {
    case A
    case B
    case C
}

Bool.enumCases()   // [false, true]
Bool.enumCount     // 2
String.enumCases() // []
String.enumCount   // 0
Int.enumCases()    // []
Int.enumCount      // 0
E.enumCases()      // [A, B, C]
E.enumCount        // 4

-1

यह एक स्थिर स्थिरांक का उपयोग कर सकता है जिसमें एन्यूमरेशन प्लस का अंतिम मान होता है।

enum Color : Int {
    case  Red, Orange, Yellow, Green, Cyan, Blue, Purple

    static let count: Int = Color.Purple.rawValue + 1

    func toUIColor() -> UIColor{
        switch self {
            case .Red:
                return UIColor.redColor()
            case .Orange:
                return UIColor.orangeColor()
            case .Yellow:
                return UIColor.yellowColor()
            case .Green:
                return UIColor.greenColor()
            case .Cyan:
                return UIColor.cyanColor()
            case .Blue:
                return UIColor.blueColor()
            case .Purple:
                return UIColor.redColor()
        }
    }
}

-3

यह मामूली है, लेकिन मुझे लगता है कि एक बेहतर ओ (1) समाधान निम्नलिखित होगा ( केवल अगर आपकी एनम Intएक्स पर शुरू हो रही है, आदि):

enum Test : Int {
    case ONE = 1
    case TWO
    case THREE
    case FOUR // if you later need to add additional enums add above COUNT so COUNT is always the last enum value 
    case COUNT

    static var count: Int { return Test.COUNT.rawValue } // note if your enum starts at 0, some other number, etc. you'll need to add on to the raw value the differential 
}

वर्तमान चयनित उत्तर मुझे अभी भी लगता है कि सभी विवरणों के लिए सबसे अच्छा उत्तर है, जब तक कि आप Intतब काम कर रहे हों, मैं इस समाधान की सलाह देता हूं।


3
अपने एनम के लिए एक मूल्य जोड़ना जो वास्तव में एनम के प्रकार का प्रतिनिधित्व नहीं करता है एक बुरा कोड गंध है। मुझे यह भी मुश्किल लगता है कि "ऑल", या "एनओएन" सहित औचित्य साबित हो सकता है, भले ही यह कभी-कभी लुभाने वाला हो। इस मुद्दे के चारों ओर हैक करने के लिए सिर्फ "COUNT" शामिल करना बहुत बदबूदार है।
माइकल पीटरसन

1
बदबूदार? यदि आप इसे सुनिश्चित करना चाहते हैं। Performant? हाँ। पेशेवरों और विपक्ष का फैसला करना डेवलपर पर निर्भर है। यह वास्तव में Zorayr के उत्तर के ऊपर एक ही उत्तर है जहां वह इसके बारे में अधिक विस्तार में जाता है, और नया स्वीकृत उत्तर भी समान है। लेकिन जब तक स्विफ्ट इसके लिए एक एप नहीं जोड़ता है; यह हम में से कुछ का उपयोग करने का फैसला किया है। प्रकारों के प्रतिनिधित्व की आपकी चिंता को हल करने के लिए आप एक फ़ंक्शन जोड़ सकते हैं जो एनुम मान को मान्य करता है जो किसी त्रुटि के guardविरुद्ध है COUNTऔर एक त्रुटि, गलत रिटर्न आदि को फेंकता है।
'13:
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.