【问题标题】:Custom hashable struct for my Dictionary我的字典的自定义哈希结构
【发布时间】:2016-06-19 07:42:49
【问题描述】:

我想构建一个可散列值用于我的字典键。它应该由一个包含两个字符串和一个 NSDate 的结构组成。我不确定我在下面正确构建了我的hashValue getter:

// MARK: comparison function for conforming to Equatable protocol
func ==(lhs: ReminderNotificationValue, rhs: ReminderNotificationValue) -> Bool {
    return lhs.hashValue == rhs.hashValue
}
struct ReminderNotificationValue : Hashable {
    var notifiedReminderName: String
    var notifiedCalendarTitle: String
    var notifiedReminderDueDate: NSDate

var hashValue : Int {
    get {
        return notifiedReminderName.hashValue &+ notifiedCalendarTitle.hashValue &+ notifiedReminderDueDate.hashValue
    }
}

init(notifiedReminderName: String, notifiedCalendarTitle: String, notifiedReminderDueDate: NSDate) {
    self.notifiedReminderName = notifiedReminderName
    self.notifiedCalendarTitle = notifiedCalendarTitle
    self.notifiedReminderDueDate = notifiedReminderDueDate
}
}


var notifications: [ReminderNotificationValue : String] = [ : ]

let val1 = ReminderNotificationValue(notifiedReminderName: "name1", notifiedCalendarTitle: "title1", notifiedReminderDueDate: NSDate())
let val2 = ReminderNotificationValue(notifiedReminderName: "name1", notifiedCalendarTitle: "title1", notifiedReminderDueDate: NSDate())

notifications[val1] = "bla1"
notifications[val2] = "bla2"

notifications[val2]   // returns "bla2". 
notifications[val1]   // returns "bla1". But I'd like the dictionary to overwrite the value for this to "bla2" since val1 and val2 should be of equal value.

【问题讨论】:

    标签: swift dictionary hashable


    【解决方案1】:

    问题不是你的hashValue 实现,而是== 函数。 通常,x == y 暗示 x.hashValue == y.hashValue,但不是 另一种方式。不同的对象可以有相同的哈希值。 甚至

    var hashValue : Int { return 1234 }
    

    将是一个无效但有效的哈希方法。

    因此,在== 中,您必须比较这两个对象以确保准确 平等:

    func ==(lhs: ReminderNotificationValue, rhs: ReminderNotificationValue) -> Bool {
        return lhs.notifiedReminderName == rhs.notifiedReminderName
        && lhs.notifiedCalendarTitle == rhs.notifiedCalendarTitle
        && lhs.notifiedReminderDueDate.compare(rhs.notifiedReminderDueDate) == .OrderedSame
    }
    

    您的代码中的另一个问题是这两个调用 NSDate() 创建不同的日期,因为 NSDate 是绝对的 时间点,表示为亚秒级的浮点数 精度。

    【讨论】:

    • 谢谢。实际上,似乎如果我通过相同的日期,那么预期的行为似乎有效。即使使用我的 == 功能。这是为什么呢?
    • @Daniel:这是偶然的。字符串的哈希值是一个 64 位数字,因此并非所有字符串都可以具有相同的哈希值。但是可能很难找到具有相同哈希的两个字符串的实际示例。 – 请注意,例如,NSArray 仅使用元素的数量作为哈希。
    • 无论我如何尝试,预期的行为都与我的原始实现完美配合。我接受你的解决方案并感谢它。但我只是想了解为什么不管我用不同的测试用例多久尝试一次,一些不应该工作的东西似乎都能工作。
    • @Daniel:哈希通常以这样一种方式创建,即两个不同的字符串“不太可能”具有相同的哈希。但是有超过 2^64 个字符串,所以也不是不可能(但很难找到一个具体的例子)。 – 有关演示问题的更简单示例,请尝试 print([1,2,3].hashValue == [4,5,6].hashValue)
    • @Daniel:可能有超过 2^64 个不同的字符串,但只有 2^64 个不同的哈希值。 “鸽子洞原理”表明,必须有不同的字符串具有相同的哈希值。
    猜你喜欢
    • 1970-01-01
    • 2018-06-07
    • 2011-05-15
    • 2018-06-23
    • 2011-06-10
    • 2011-12-17
    • 2020-05-29
    • 2013-12-29
    • 1970-01-01
    相关资源
    最近更新 更多