swift 是否符合哈希协议?

m4pnthwp  于 2022-12-17  发布在  Swift
关注(0)|答案(7)|浏览(132)

我试图创建一个字典,把键作为我创建的结构体,把值作为一个整数数组,但是,我总是得到错误:
类型“DateStruct”不符合协议“哈希"
我确信我已经实现了必要的方法,但由于某种原因,它仍然不起作用。
下面是我的结构和实现的协议:

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
                }
            }
        }
    }
}

有人能解释一下为什么我还是会收到错误吗?

xwbd5t1u

xwbd5t1u1#

你忘了宣言:

struct DateStruct: Hashable {

而且你的==函数是错误的,你应该比较一下这三个属性。

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

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

ne5o7dgx

ne5o7dgx2#

var hashValue: Int

仍然适用于旧版NSObject继承树,否则将被废弃。

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

是在课堂上快速而现代地乱讲的方法。
根据上面的rmaddy答案,“==”操作符也必须解决一些问题,才能符合您的语义。
根据Manish的说法,你可以免费获得结构体的哈希一致性,只要声明一下。

v09wglhw

v09wglhw3#

如果类具有类型的字段(另一个类),则该类应该采用哈希表。
范例

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

}

这里,Activity类也必须采用哈希表。

kq0g1dla

kq0g1dla4#

如果不想使用hashValue,可以将值的散列与hash(into:)方法结合使用。
有关详细信息,请参阅答案:https://stackoverflow.com/a/55118328/1261547

gv8xihay

gv8xihay5#

对于简单的结构体,它的所有属性都已经是Hashable(即IntString,...),我们只需声明它就可以符合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
        }
    }
}
zu0ti5jz

zu0ti5jz6#

定义结构时未指定哈希协议:
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
tcomlyy6

tcomlyy67#

public struct HistoryFilePair : Hashable {
    //this
    public static func == (lhs: HistoryFilePair, rhs: HistoryFilePair) -> Bool {
        lhs.commit.oidShort == rhs.commit.oidShort
    }
    
    // this
    public func hash(into hasher: inout Hasher) {
        return hasher.combine(self.commit.oidShort)
    }

    //some code of your struct/class
}

相关问题