符合Hashable协议?

时间:2017-02-22 04:50:20

标签: swift struct swift3 hashable

我正在尝试使用键创建一个字典作为我创建的结构,并将值作为Ints数组。但是,我一直收到错误:struct dateStruct { var year: Int var month: Int var day: Int var hashValue: Int { return (year+month+day).hashValue } static func == (lhs: dateStruct, rhs: dateStruct) -> Bool { return lhs.hashValue == rhs.hashValue } static func < (lhs: dateStruct, rhs: dateStruct) -> Bool { if (lhs.year < rhs.year) { return true } else if (lhs.year > rhs.year) { return false } else { if (lhs.month < rhs.month) { return true } else if (lhs.month > rhs.month) { return false } else { if (lhs.day < rhs.day) { return true } else { return false } } } } } 。我很确定我已经实现了必要的方法但由于某种原因它仍然不起作用。这是我的结构与实现的协议:

+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
| name         | descr             | adminSt | authSt   | server_hostname_ip | server_descr | server_preferred | server_EPG  | server_minPol | server_maxPoll |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
| test1-NTPPOL | Test NTP Policy   | enabled | disabled | 10.10.10.10        | NTP1 server  | yes              | oob-default | 4             | 6              |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
|              |                   |         |          | 10.10.10.11        | NTP2 server  | no               | oob-default | 4             | 6              |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
|              |                   |         |          | 10.10.10.12        | NTP3 server  | no               | oob-default | 4             | 6              |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
| test2-NTPPOL | Test 2 NTP policy | enabled | disabled | 20.10.10.10        | NTP1 server  | yes              | oob-default | 4             | 6              |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
|              |                   |         |          | 20.10.10.11        | NTP2 server  | no               | oob-default | 4             | 6              |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+
|              |                   |         |          | 20.10.10.12        | NTP3 server  | no               | oob-default | 4             | 6              |
+--------------+-------------------+---------+----------+--------------------+--------------+------------------+-------------+---------------+----------------+

有人可以向我解释为什么我仍然会收到错误吗?

6 个答案:

答案 0 :(得分:19)

你错过了宣言:

struct dateStruct: Hashable {

BTW - 结构和类名称应以大写字母开头。

您的==功能错误。你应该比较这三个属性。

static func == (lhs: dateStruct, rhs: dateStruct) -> Bool {
    return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day
}

两个不同的值可能具有相同的哈希值。

答案 1 :(得分:3)

顺便说一句

var hashValue: Int 

已过时(在旧版NSObject继承树中除外)。

func hash(into hasher: inout Hasher)
    {
        hasher.combine(year);
        hasher.combine(month) 
    ...

是新方法

答案 2 :(得分:2)

如果该类具有类型(另一个类)的字段,则该类应采用 Hashable。

示例

struct Project : Hashable {
    var activities: [Activity]?

}

这里,Activity类也必须采用Hashable。

答案 3 :(得分:1)

在定义struct:struct dateStruct: Hashable {...

时未指定Hashable协议

以下代码来自您的示例,它在Playground上运行。请注意您的==运算符已在此处修改

import Foundation

struct dateStruct: Hashable {
    var year: Int
    var month: Int
    var day: Int

    var hashValue: Int {
        return (year+month+day).hashValue
    }

    static func == (lhs: dateStruct, rhs: dateStruct) -> Bool {
        return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day
    }

    static func < (lhs: dateStruct, rhs: dateStruct) -> Bool {
        if (lhs.year < rhs.year) {
            return true
        } else if (lhs.year > rhs.year) {
            return false
        } else {
            if (lhs.month < rhs.month) {
                return true
            } else if (lhs.month > rhs.month) {
                return false
            } else {
                if (lhs.day < rhs.day) {
                    return true
                } else {
                    return false
                }
            }
        }
    }
}

var d0 = dateStruct(year: 2017, month: 2, day: 21)
var d1 = dateStruct(year: 2017, month: 2, day: 21)

var dates = [dateStruct:Int]()
dates[d0] = 23
dates[d1] = 49

print(dates)

print(d0 == d1) // true

d0.year = 2018

print(d0 == d1) // false

答案 4 :(得分:1)

如果您不想使用hashValue,可以将值的哈希值与hash(into:)方法结合使用。

有关更多信息,请参见答案:https://stackoverflow.com/a/55118328/1261547

答案 5 :(得分:0)

对于简单结构,其所有属性已经为Hashable(即IntString,...),我们可以遵循Hashable只是声明它(参见https://developer.apple.com/documentation/swift/hashable

因此无需实现hashValue(不推荐使用btw)或==(因为Hashable符合Equatable)。

由于我们正在实现<运算符,因此符合Comparable是有意义的,因此我们可以进行排序(即[dateStructA, dateStructB, ...].sorted())。

所以我会这样做:

struct DateStruct: Comparable & Hashable {
    let year: Int
    let month: Int
    let day: Int

    static func < (lhs: DateStruct, rhs: DateStruct) -> Bool {
        if lhs.year != rhs.year {
           return lhs.year < rhs.year
        } else if lhs.month != rhs.month {
           return lhs.month < rhs.month
        } else {
           return lhs.day < rhs.day
        }
    }
}
相关问题