符合 Hashable 协议?
Conforming to Hashable protocol?
我正在尝试制作一个字典,其中键作为我创建的结构,值作为 Ints 数组。但是,我不断收到错误消息:
Type 'DateStruct' does not conform to protocol 'Hashable'
我很确定我已经实施了必要的方法,但由于某些原因它仍然不起作用。
这是我实现的协议结构:
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
}
}
}
}
}
任何人都可以向我解释为什么我仍然收到错误消息吗?
您缺少声明:
struct DateStruct: Hashable {
而您的 ==
函数是错误的。你应该比较这三个属性。
static func == (lhs: DateStruct, rhs: DateStruct) -> Bool {
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day
}
两个不同的值可能具有相同的哈希值。
您在定义结构时没有指定 Hashable 协议:
struct DateStruct: 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
如果您不想使用 hashValue,可以将您的值的散列与 hash(into:)
方法结合起来。
有关详细信息,请参阅答案:
var hashValue: Int
已过时(遗留 NSObject 继承树除外)。
func hash(into hasher: inout Hasher)
{
hasher.combine(year);
hasher.combine(month)
...
是在 class.
中散列方式的快速现代方式
根据上面的 rmaddy 回答,“==”运算符还必须解决一些问题才能正确符合您的语义。
根据 Manish,您只需声明即可免费获得结构的 Hashable 一致性。
对于简单的结构,其所有属性都已经是 Hashable
(即 Int
、String
、...),我们可以符合 Hashable
只是声明它(见 https://developer.apple.com/documentation/swift/hashable )
因此无需实施 hashValue
(顺便说一句,已弃用)或 ==
(因为 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
}
}
}
如果class有字段类型(另一个class),那class应该采用Hashable。
例子
struct Project : Hashable {
var activities: [Activity]?
}
这里Activityclass也必须采用Hashable
我正在尝试制作一个字典,其中键作为我创建的结构,值作为 Ints 数组。但是,我不断收到错误消息:
Type 'DateStruct' does not conform to protocol 'Hashable'
我很确定我已经实施了必要的方法,但由于某些原因它仍然不起作用。
这是我实现的协议结构:
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
}
}
}
}
}
任何人都可以向我解释为什么我仍然收到错误消息吗?
您缺少声明:
struct DateStruct: Hashable {
而您的 ==
函数是错误的。你应该比较这三个属性。
static func == (lhs: DateStruct, rhs: DateStruct) -> Bool {
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day
}
两个不同的值可能具有相同的哈希值。
您在定义结构时没有指定 Hashable 协议:
struct DateStruct: 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
如果您不想使用 hashValue,可以将您的值的散列与 hash(into:)
方法结合起来。
有关详细信息,请参阅答案:
var hashValue: Int
已过时(遗留 NSObject 继承树除外)。
func hash(into hasher: inout Hasher)
{
hasher.combine(year);
hasher.combine(month)
...
是在 class.
中散列方式的快速现代方式根据上面的 rmaddy 回答,“==”运算符还必须解决一些问题才能正确符合您的语义。
根据 Manish,您只需声明即可免费获得结构的 Hashable 一致性。
对于简单的结构,其所有属性都已经是 Hashable
(即 Int
、String
、...),我们可以符合 Hashable
只是声明它(见 https://developer.apple.com/documentation/swift/hashable )
因此无需实施 hashValue
(顺便说一句,已弃用)或 ==
(因为 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
}
}
}
如果class有字段类型(另一个class),那class应该采用Hashable。
例子
struct Project : Hashable {
var activities: [Activity]?
}
这里Activityclass也必须采用Hashable