dictionary - tag - took ka matlab




मैं स्विफ्ट एन्यूम को एक शब्दकोश कुंजी के रूप में कैसे उपयोग कर सकता हूं?(समानता के अनुरूप) (3)

मुझे कुछ हद तक प्रयास करने के लिए संघर्ष करने की कोशिश की, जो कि संबद्ध मूल्यों के साथ एक enum बनाने की कोशिश करता है।

यहां मैंने अपने मान को संबद्ध मानों के साथ Hashable अनुरूप बना दिया Hashable ताकि इसे सॉर्ट किया जा सकता है या Dictionary कुंजी के रूप में इस्तेमाल किया जा सकता है, या जो कुछ भी Hashable कर सकता है

आपको अपने संबंधित मूल्यों को Hashable बनाने के लिए करना चाहिए, क्योंकि संबद्ध मूल्यों में एक कच्चे प्रकार नहीं हो सकते हैं।

public enum Components: Hashable {
    case None
    case Year(Int?)
    case Month(Int?)
    case Week(Int?)
    case Day(Int?)
    case Hour(Int?)
    case Minute(Int?)
    case Second(Int?)

    ///The hashValue of the `Component` so we can conform to `Hashable` and be sorted.
    public var hashValue : Int {
        return self.toInt()
    }

    /// Return an 'Int' value for each `Component` type so `Component` can conform to `Hashable`
    private func toInt() -> Int {
        switch self {
        case .None:
            return -1
        case .Year:
            return 0
        case .Month:
            return 1
        case .Week:
            return 2
        case .Day:
            return 3
        case .Hour:
            return 4
        case .Minute:
            return 5
        case .Second:
            return 6
        }

    }

}

इसके अलावा समानता ऑपरेटर को ओवरराइड करना भी आवश्यक है:

/// Override equality operator so Components Enum conforms to Hashable
public func == (lhs: Components, rhs: Components) -> Bool {
    return lhs.toInt() == rhs.toInt()
}

मैंने "स्टेशन" के चयन का प्रतिनिधित्व करने के लिए एक मान परिभाषित किया है; स्टेशनों को एक विशिष्ट सकारात्मक पूर्णांक द्वारा परिभाषित किया जाता है, इसलिए मैंने निम्न मान को विशेष चयनों का प्रतिनिधित्व करने के लिए नकारात्मक मूल्यों को अनुमति देने के लिए बनाया है:

enum StationSelector : Printable {
    case Nearest
    case LastShown
    case List
    case Specific(Int)

    func toInt() -> Int {
        switch self {
        case .Nearest:
            return -1
        case .LastShown:
            return -2
        case .List:
            return -3
        case .Specific(let stationNum):
            return stationNum
        }
    }

    static func fromInt(value:Int) -> StationSelector? {
        if value > 0 {
            return StationSelector.Specific(value)
        }
        switch value {
        case -1:
            return StationSelector.Nearest
        case -2:
            return StationSelector.LastShown
        case -3:
            return StationSelector.List
        default:
            return nil
        }
    }

    var description: String {
    get {
        switch self {
        case .Nearest:
            return "Nearest Station"
        case .LastShown:
            return "Last Displayed Station"
        case .List:
            return "Station List"
        case .Specific(let stationNumber):
            return "Station #\(stationNumber)"
        }
    }
    }
}

मैं इन मानों को एक शब्दकोश में कुंजी के रूप में उपयोग करना चाहता हूं एक डिक्शनरी की घोषणा करने से अपेक्षित त्रुटि उत्पन्न होती है कि स्टेशनशिपक हाशनीय के अनुरूप नहीं होता है। हाशनीय के अनुरूप होना एक सरल हैश फ़ंक्शन के साथ आसान है:

var hashValue: Int {
get {
    return self.toInt()
}
}

हालांकि, Equatable को Equatable करने के लिए अनुरूप होना Equatable , और मैं कंपाइलर को संतुष्ट करने के लिए अपने Equatable के बराबर ऑपरेटर को परिभाषित नहीं कर सकता।

func == (lhs: StationSelector, rhs: StationSelector) -> Bool {
    return lhs.toInt() == rhs.toInt()
}

कंपाइलर शिकायत करता है कि यह एक पंक्ति पर दो घोषणाएं हैं और एक रखना चाहता है ; func बाद, जो समझ में नहीं आता है, या तो

कोई विचार?


शब्दकोश कुंजी के रूप में एन्यूमरेशन पर जानकारी:

स्विफ्ट बुक से:

गणना मूल्यों के बिना मूल्यों के मूल्यों को मान (जैसा कि एन्यूमरेशन में वर्णित है) भी डिफ़ॉल्ट रूप से भी हैं।

हालांकि, आपकी गणना में संबद्ध मूल्य के साथ एक सदस्य का मान होता है, इसलिए आपके द्वारा मैन्युअल रूप से Hashable अनुरूपता Hashable होगी

उपाय

आपके कार्यान्वयन के साथ समस्या, यह है कि स्विफ्ट में ऑपरेटर घोषणा वैश्विक स्तर पर होनी चाहिए।

बस चलें:

func == (lhs: StationSelector, rhs: StationSelector) -> Bool {
    return lhs.toInt() == rhs.toInt()
}

enum परिभाषा के बाहर और यह काम करेगा।

उस पर और अधिक के लिए दस्तावेज़ों की जांच करें।


अधिक पठनीयता के लिए, चलो स्विफ्ट 3 के साथ StationSelector को पुन:

enum StationSelector {
    case nearest, lastShown, list, specific(Int)
}

extension StationSelector: RawRepresentable {

    typealias RawValue = Int

    init?(rawValue: RawValue) {
        switch rawValue {
        case -1: self = .nearest
        case -2: self = .lastShown
        case -3: self = .list
        case (let value) where value >= 0: self = .specific(value)
        default: return nil
        }
    }

    var rawValue: RawValue {
        switch self {
        case .nearest: return -1
        case .lastShown: return -2
        case .list: return -3
        case .specific(let value) where value >= 0: return value
        default: fatalError("StationSelector is not valid")
        }
    }

}

एप्पल डेवलपर एपीआई संदर्भ Hashable प्रोटोकॉल के बारे में बताता है:

जब आप किसी मूल्य के बिना एक गणन को परिभाषित करते हैं, तो यह अपने आप में Hashable अनुरूपता प्राप्त कर लेता है, और आप एक भी hashValue संपत्ति जोड़कर अपने अन्य कस्टम प्रकारों के लिए hashValue अनुरूपता जोड़ सकते हैं।

इसलिए, क्योंकि StationSelector संबद्ध मान लागू करता है, आपको Hashable मैन्युअल रूप से Hashable प्रोटोकॉल के अनुरूप बनाना चाहिए।

पहला कदम == ऑपरेटर को कार्यान्वित करना है और Equatable प्रोटोकॉल के अनुरूप है:

extension StationSelector: Equatable {

    static func == (lhs: StationSelector, rhs: StationSelector) -> Bool {
        return lhs.rawValue == rhs.rawValue
    }

}

उपयोग:

let nearest = StationSelector.nearest
let lastShown = StationSelector.lastShown
let specific0 = StationSelector.specific(0)

// Requires == operator
print(nearest == lastShown) // prints false
print(nearest == specific0) // prints false

// Requires Equatable protocol conformance
let array = [nearest, lastShown, specific0]
print(array.contains(nearest)) // prints true

एक बार Equatable प्रोटोकॉल लागू किया जाता है, तो आप Equatable प्रोटोकॉल के अनुरूप बना सकते हैं:

extension StationSelector: Hashable {

    var hashValue: Int {
        return self.rawValue.hashValue
    }

}

उपयोग:

// Requires Hashable protocol conformance
let dictionnary = [StationSelector.nearest: 5, StationSelector.lastShown: 10]

निम्नलिखित कोड, StationSelector लिए आवश्यक कार्यान्वयन को दिखाता है ताकि इसे स्विफ्ट 3 का प्रयोग करके Hashable प्रोटोकॉल के अनुरूप बनाया जा सके:

enum StationSelector: RawRepresentable, Hashable {

    case nearest, lastShown, list, specific(Int)

    typealias RawValue = Int

    init?(rawValue: RawValue) {
        switch rawValue {
        case -1: self = .nearest
        case -2: self = .lastShown
        case -3: self = .list
        case (let value) where value >= 0: self = .specific(value)
        default: return nil
        }
    }

    var rawValue: RawValue {
        switch self {
        case .nearest: return -1
        case .lastShown: return -2
        case .list: return -3
        case .specific(let value) where value >= 0: return value
        default: fatalError("StationSelector is not valid")
        }
    }

    static func == (lhs: StationSelector, rhs: StationSelector) -> Bool {
        return lhs.rawValue == rhs.rawValue
    }

    var hashValue: Int {
        return self.rawValue.hashValue
    }

}




hashable