如何将Swift枚举用作词典键?(符合Equatable)

Dou*_*les 35 enums dictionary hashable swift

我已经定义了一个枚举来代表一个"站"的选择; station由唯一的正整数定义,因此我创建了以下枚举,以允许负值表示特殊选择:

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)"
        }
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想将这些值用作字典中的键.声明字典会产生StationSelector不符合Hashable的预期错误.使用简单的哈希函数可以轻松地符合Hashable:

var hashValue: Int {
get {
    return self.toInt()
}
}
Run Code Online (Sandbox Code Playgroud)

但是,Hashable需要符合Equatable,我似乎无法在我的枚举上定义equals运算符来满足编译器.

func == (lhs: StationSelector, rhs: StationSelector) -> Bool {
    return lhs.toInt() == rhs.toInt()
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨这是一行上的两个声明,并且想要放一个;after func,这也没有意义.

有什么想法吗?

Cez*_*zar 24

枚举信息作为字典键:

从Swift书中:

默认情况下,没有关联值的枚举成员值(如枚举中所述)也是可清除的.

但是,您的枚举确实具有带有关联值的成员值,因此Hashable必须由您手动添加一致性.

您的实现的问题是Swift中的运算符声明必须在全局范围内.

移动:

func == (lhs: StationSelector, rhs: StationSelector) -> Bool {
    return lhs.toInt() == rhs.toInt()
}
Run Code Online (Sandbox Code Playgroud)

enum定义之外,它将起作用.

有关详细信息,请查看文档.


Sak*_*boy 6

我努力尝试使enum相关值符合Hashable.

这是我使我enum的关联值符合,Hashable因此它可以被排序或用作Dictionary键,或做任何其他Hashable可以做的事情.

您必须使关联值enum符合,Hashable因为关联值enums不能具有原始类型.

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
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

还需要覆盖相等运算符:

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