标签: hashable

如何在Swift中处理字典的哈希冲突

TLDR

我的自定义结构实现了Hashable Protocol.但是,当在a中插入密钥时发生散列冲突时Dictionary,它们不会自动处理.我该如何克服这个问题?

背景

我之前曾问过这个问题 如何在Swift中为Int数组(自定义字符串结构)实现Hashable Protocol.后来我添加了自己的答案,这似乎有效.

但是,最近我hashValue在使用a时发现了碰撞的微妙问题Dictionary.

最基本的例子

我尽可能地将代码简化为以下示例.

定制结构

struct MyStructure: Hashable {

    var id: Int

    init(id: Int) {
        self.id = id
    }

    var hashValue: Int {
        get {
            // contrived to produce a hashValue collision for id=1 and id=2
            if id == 1 {
                return 2 
            }
            return id
        }
    }
}

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

请注意全局函数重载相等运算符(==)以符合 …

dictionary hash-collision hashable swift

14
推荐指数
2
解决办法
2199
查看次数

创建表示可以打开或关闭的可打包对象的协议

我正在尝试创建一个简单的协议,说明对象是处于"开启"状态还是"关闭"状态.对此的解释取决于实施对象.对于a UISwitch,无论开关是打开还是关闭(duh).对于a UIButton,可能是按钮是否处于selected状态.对于a Car,可能是汽车的引擎是否打开,或者即使它是否在移动.所以我开始创建这个简单的协议:

protocol OnOffRepresentable {
    func isInOnState() -> Bool
    func isInOffState() -> Bool
}
Run Code Online (Sandbox Code Playgroud)

现在我可以扩展前面提到的UI控件,如下所示:

extension UISwitch: OnOffRepresentable {
    func isInOnState() -> Bool { return on }
    func isInOffState() -> Bool { return !on }
}

extension UIButton: OnOffRepresentable {
    func isInOnState() -> Bool { return selected }
    func isInOffState() -> Bool { return !selected }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以创建这些类型的对象的数组并循环它,检查它们是打开还是关闭:

let booleanControls: [OnOffRepresentable] = [UISwitch(), UIButton()]
booleanControls.forEach { print($0.isInOnState()) }
Run Code Online (Sandbox Code Playgroud)

大!现在我想创建一个将这些控件映射到a的字典,UILabel以便在控件更改状态时更改与控件关联的标签的文本.所以我去宣布我的字典:

var toggleToLabelMapper: …
Run Code Online (Sandbox Code Playgroud)

protocols type-erasure ios hashable swift

10
推荐指数
1
解决办法
2574
查看次数

如何在Python中测试"任何深度的不变性"?

我将Python对象定义为"在任何深度都是不可变的"iff

  1. 它(名义上)是不可改变的;
  2. 如果它是一个"容器"对象,那么它只包含"在任何深度都是不可变的"对象;

例如((1, 2), (3, 4)),在任何深度都是不可变的,而((1, 2), [3, 4])不是(尽管后者,由于是一个元组,"名义上"是不可变的).

有没有合理的方法来测试Python对象是否"在任何深度都是不可变的"?

测试第一个条件相对容易(例如使用collections.Hashable类,忽略了不正确实现__hash__方法的可能性),但第二个条件更难以测试,因为"容器"对象的异质性,以及迭代他们的"内容"......

谢谢!

python nested immutability hashable

9
推荐指数
1
解决办法
515
查看次数

元类型(.Type)可以用作字典中的键吗?

我有这样的事情:

class Lumber { }
class Fruit { }

enum Size {
    case small
    case medium
    case large
}

let lumberSize = [
    Size.small: "2x4",
    Size.medium: "4x6",
    Size.large: "6x10"
]

let fruitSize = [
    Size.small: "grape",
    Size.medium: "apple",
    Size.large: "watermelon"
]

let size:[AnyObject.Type:Dictionary] = [
    Lumber.Type: lumberSize,
    Fruit.Type: fruitSize
]
Run Code Online (Sandbox Code Playgroud)

在我的size字典定义中,我从Xcode编辑器中得到了这个实时错误:

类型'AnyObject.Type'不符合协议'Hashable'

你可能认为这会解决问题.如果我想在字典中使用X作为键,并且它不可以使用,则它根本无法使用.那讲得通.

但是,有两件事让我怀疑错误信息.

首先,此时实时Xcode编辑器错误消息超出基本要求.每天好几次,我必须忽略它对错误的猜测,并在语法被接受之前使用它.

其次,我想在文档中读取反驳错误消息的单词.在Swift 2.2语言参考中,在类型下,它显示为:

类,结构或枚举类型的元类型是该类型的名称,后跟.Type

并在Swift标准库参考 ObjectIdentifier结构参考中读取:

在Swift中,只有类实例和元类型具有唯一的标识.

该部分还列出size了它符合的协议.

如果我正确阅读,那么所有类型都有 ObjectIdentifier Hashable使用的类型.我(错误地?)使用Comparable作为例子.我们可以比较类型,因为它们的ObjectIdentifier符合Comparable?既然ObjectIdentifier也符合Hashable,那么我应该能够在字典中使用它.

所以现在我怀疑我打算做的事实际上是可行的,但是我根本无法使语法正确.

xcode dictionary hashable swift

9
推荐指数
1
解决办法
847
查看次数

符合Hashable协议?

我正在尝试使用键创建一个字典作为我创建的结构,并将值作为Ints数组.但是,我不断收到错误:__CODE__.我很确定我已经实现了必要的方法但由于某种原因它仍然不起作用.这是我的结构与实现的协议:

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) { …
Run Code Online (Sandbox Code Playgroud)

struct hashable swift swift3

9
推荐指数
4
解决办法
1万
查看次数

仅考虑 id 来符合 Hashable 是否正确?

我遇到了很多在线示例,当他们尝试符合时Hashable,他们只考虑id考虑。例如https://www.raywenderlich.com/8241072-ios-tutorial-collection-view-and-diffable-data-source , https://medium.com/@JoyceMatos/hashable-protocols-in-swift-baf0cabeaebd , ...

/// Copyright (c) 2020 Razeware LLC
/// 
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// …
Run Code Online (Sandbox Code Playgroud)

hashable swift

9
推荐指数
2
解决办法
758
查看次数

推荐的实现__eq__和__hash__的方法

Python文档中提到,如果重写__eq__和对象是不可变的,你也应该重写__hash__为了类是正确哈希的。

在实践中,当我这样做时,我通常会得到如下代码

class MyClass(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __eq__(self, other):
        if type(other) is type(self):
            return (self.a == other.a) and (self.b == other.b)
        else:
            return False

    def __hash__(self):
        return hash((self.a, self.b))
Run Code Online (Sandbox Code Playgroud)

这在某种程度上是重复的,并且很明显有在更新另一个更新时忘记更新一个的风险。

是否有建议的方法一起实现这些方法?

python equality hashable

7
推荐指数
1
解决办法
2311
查看次数

NSObject是Hashable但是采用NSObject的协议不是吗?

在我提交雷达之前,只需与社区进行健全检查:

在.h Obj-C文件中:

@protocol myProto <NSObject> 
@end
Run Code Online (Sandbox Code Playgroud)

在.swift文件中(可通过桥接头访问上述协议定义):

class myClass {
    // This line compiles fine
    var dictOne: [NSObject:Int]?
    // This line fails with "Type 'myProto' does not conform to protocol 'Hashable'"
    var dictTwo: [myProto:Int]?
}
Run Code Online (Sandbox Code Playgroud)

NSObject类的检验表明,它(或NSObjectProtocol它映射到)不执行由所述哈希的协议所需的散列值的方法,也没有明确地通过.

所以,在幕后的某个地方,尽管如此,NSObject仍被标记为Hashable,但不会扩展到采用NSObject/NSObjectProtocol的协议.

我有错误或错过了什么吗?

:) Teo

附加信息:

文件表明:

  • 字典的密钥类型的唯一要求是它是Hashable并且它实现了==.
  • 你确实可以使用协议.
字典键类型的哈希值

类型必须是可散列的才能用作字典的键类型 - 也就是说,类型必须提供计算自身散列值的方法.散列值是一个Int值,是对于比较相等的所有对象中,相同的,使得如果一个== B,它遵循a.hashValue == b.hashValue.

所有斯威夫特的基本类型(如字符串,整数,双精度和布尔)的默认情况下可哈希的,而所有这些类型的可以作为一个字典的键.默认情况下,没有关联值的枚举成员值(如枚举中所述)也是可清除的.

注意您可以使用自己的自定义类型作为字典键类型,使其符合Swift标准库中的Hashable协议.符合所述哈希的协议类型必须提供一个gettable int属性称为散列值,并且还必须提供"等于"运算符(==)的实现.类型的hashValue属性返回的值在同一程序的不同执行或不同程序中不需要相同.有关符合协议的更多信息,请参阅协议.

protocols objective-c hashable swift

6
推荐指数
1
解决办法
4600
查看次数

Swift:具有字典属性的Hashable结构

我在Swift中有一个结构,如下所示:

internal struct MapKey {
    internal let id: String
    internal let values: [String:String]
}
extension MapKey: Equatable {}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
    return lhs.id == rhs.id && lhs.values == rhs.values
}
Run Code Online (Sandbox Code Playgroud)

我现在需要使用MapKey作为Swift字典中的键,这需要MapKey符合Hashable协议.

对于像这样的结构,Hashable的正确实现是什么?

extension MapKey: Hashable {
    var hashValue: Int {
        return ??? // values does not have a hash function/property.
    }
}
Run Code Online (Sandbox Code Playgroud)

我一直在做一些研究,但未能确定散列字典的正确方法是什么,因为我需要能够为values属性本身生成散列值.任何帮助深表感谢.

hashable swift equatable

6
推荐指数
1
解决办法
2105
查看次数

Make a swift protocol conform to Hashable

I'm going around in circles trying to get Hashable to work with multiple struct that conform to the same protocol.

I have a protocol SomeLocation declared like this:

protocol SomeLocation {
    var name:String { get }
    var coordinates:Coordinate { get }
}
Run Code Online (Sandbox Code Playgroud)

Then I create multiple objects that contain similar data like this:

struct ShopLocation: SomeLocation, Decodable {
    var name: String
    var coordinates: Coordinate

    init(from decoder: Decoder) throws {
        ...
    }
}

struct CarLocation: SomeLocation, Decodable {
    var name: …
Run Code Online (Sandbox Code Playgroud)

protocols ios hashable swift swift-protocols

6
推荐指数
1
解决办法
1432
查看次数