स्विफ्ट में अपने संबंधित मूल्य की अनदेखी करके संबंधित मूल्यों के साथ दुश्मनी की तुलना कैसे करें?


90

संबंधित मूल्यों के साथ स्विफ्ट एनम की समानता का परीक्षण करने के तरीके को पढ़ने के बाद , मैंने निम्नलिखित एनम को लागू किया:

enum CardRank {
    case Number(Int)
    case Jack
    case Queen
    case King
    case Ace
}

func ==(a: CardRank, b: CardRank) -> Bool {
    switch (a, b) {
    case (.Number(let a), .Number(let b))   where a == b: return true
    case (.Jack, .Jack): return true
    case (.Queen, .Queen): return true
    case (.King, .King): return true
    case (.Ace, .Ace): return true
    default: return false
    }
}

निम्नलिखित कोड काम करता है:

let card: CardRank = CardRank.Jack
if card == CardRank.Jack {
    print("You played a jack!")
} else if card == CardRank.Number(2) {
    print("A two cannot be played at this time.")
}

हालाँकि, यह संकलन नहीं है:

let number = CardRank.Number(5)
if number == CardRank.Number {
    print("You must play a face card!")
}

... और यह निम्न त्रुटि संदेश देता है:

बाइनरी ऑपरेटर '==' को 'कार्डरैंक' और '(इंट) -> कार्डरैंक' के प्रकारों पर लागू नहीं किया जा सकता है

मैं यह मान रहा हूं क्योंकि यह एक पूर्ण प्रकार की उम्मीद कर रहा है और CardRank.Numberएक पूरे प्रकार को निर्दिष्ट नहीं करता है, जबकि CardRank.Number(2)किया। हालाँकि, इस मामले में, मैं चाहता हूं कि यह किसी भी संख्या से मेल खाए ; सिर्फ एक विशिष्ट नहीं।

जाहिर है मैं एक स्विच स्टेटमेंट का उपयोग कर सकता हूं, लेकिन ==ऑपरेटर को लागू करने का पूरा बिंदु इस क्रिया समाधान से बचना था:

switch number {
case .Number:
    print("You must play a face card!")
default:
    break
}

क्या संबंधित मूल्य की अनदेखी करते हुए संबंधित मूल्यों के साथ एक दुश्मनी की तुलना करने का कोई तरीका है?

नोट: मुझे एहसास है कि मैं मामले को ==विधि में बदल सकता हूं case (.Number, .Number): return true, लेकिन, हालांकि यह सही ढंग से वापस आ जाएगा, मेरी तुलना अभी भी किसी विशिष्ट संख्या की तुलना में इसकी तुलना में दिखाई देगी ( number == CardRank.Number(2)जहां 2 किसी भी संख्या के बजाय एक डमी मूल्य है); ( number == CardRank.Number)।


1
आप कम कर सकते हैं Jack, Queen, King, Aceमें मामलों ==: बस ऑपरेटर कार्यान्वयनcase (let x, let y) where x == y: return true
अलेक्जेंडर

जवाबों:


76

संपादित करें: जैसा कि ईटन बताते हैं, आप (_)वाइल्डकार्ड मैच को और अधिक सफाई से उपयोग करने के लिए छोड़ सकते हैं ।


दुर्भाग्य से, मुझे विश्वास नहीं है कि switchस्विफ्ट 1.2 में आपके दृष्टिकोण से आसान तरीका है ।

स्विफ्ट 2 में, हालांकि, आप नए if-caseपैटर्न मैच का उपयोग कर सकते हैं :

let number = CardRank.Number(5)
if case .Number(_) = number {
    // Is a number
} else {
    // Something else
}

यदि आप शब्दाडंबर से बचने के लिए देख रहे हैं, तो आप isNumberअपने enum में एक गणना की गई संपत्ति जोड़ने पर विचार कर सकते हैं जो आपके स्विच स्टेटमेंट को लागू करती है।


1
यह नियंत्रण प्रवाह के लिए बहुत अच्छा है, लेकिन यह थोड़े बेकार है जब आप केवल एक सरल अभिव्यक्ति चाहते हैं, जैसे assert(number == .Number):। मैं केवल यही आशा कर सकता हूं कि स्विफ्ट के बाद के संस्करणों में सुधार किया जाए। = /
जेरेमी

3
लूप की स्थिति आदि जैसी चीजों के लिए भी बेकार है। स्विफ्ट 3 में आप क्लीनर कोड के लिए (_) निकाल सकते हैं।
Etan

धन्यवाद @ ईटन, मैंने उस उत्तर को जोड़ दिया है। आप वास्तव में स्विफ्ट 2 में भी वाइल्डकार्ड को छोड़ सकते हैं। भाषा सुविधा जारी होने से पहले यह उत्तर लिखा गया था, इसलिए मुझे अभी तक पता नहीं था! :-D
रोनाल्ड मार्टिन

इसके अलावा: यदि किसी सम्‍मिलित मामले में संबद्ध मानों के साथ एकल केस है, तो उन मामलों के लिए भी यदि मामले में संबंधित मानों का उपयोग नहीं किया जाना चाहिए
इतन

1
@PeterWarbo, आप इस पैटर्न-मिलान वाक्यविन्यास के साथ निषेध नहीं कर सकते। अब आपको defaultएक switchब्लॉक में एक मामले में वापस आना होगा ।
रोनाल्ड मार्टिन

29

दुर्भाग्य से स्विफ्ट 1.x में ऐसा कोई दूसरा तरीका नहीं है जिससे आपको उपयोग करना पड़े switchजो कि स्विफ्ट 2 के संस्करण की तरह सुरुचिपूर्ण नहीं है जहाँ आप उपयोग कर सकते हैं if case:

if case .Number = number {
    //ignore the value
}
if case .Number(let x) = number {
    //without ignoring
}

3
अफसोस की बात है, यह केवल ifबयानों में काम करता है , न कि एक अभिव्यक्ति के रूप में।
राफेल

20

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

enum CardRank: Equatable {
    case Number(Int)
    case Jack
    case Queen
    case King
    case Ace
}

https://developer.apple.com/documentation/swift/equatable?changes=_3


19
हालांकि यह संबद्ध मूल्यों की तुलना करेगा।
जो

3

यहाँ एक सरल तरीका है:

enum CardRank {
    case Two
    case Three
    case Four
    case Five
    case Six
    case Seven
    case Eight
    case Nine
    case Ten
    case Jack
    case Queen
    case King
    case Ace

    var isFaceCard: Bool {
        return (self == Jack) || (self == Queen) || (self == King)
    }
}

== ऑपरेटर को ओवरलोड करने की कोई आवश्यकता नहीं है, और कार्ड के प्रकार की जांच के लिए भ्रामक वाक्यविन्यास की आवश्यकता नहीं है:

let card = CardRank.Jack

if card == CardRank.Jack {
    print("You played a jack")
} else if !card.isFaceCard {
    print("You must play a face card!")
}

3
यद्यपि यह ओवररचिंग प्रश्न का उत्तर नहीं देता है, IMO यह एक अधिक सुरुचिपूर्ण समाधान है (अलग-अलग संख्याओं को अलग करता है) ओपी के समान परिदृश्यों में और इसे डाउनवोट नहीं किया जाना चाहिए।
नाथन होसलटन

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