我的自定义结构实现了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)
请注意全局函数重载相等运算符(==)以符合 …
我正在尝试创建一个简单的协议,说明对象是处于"开启"状态还是"关闭"状态.对此的解释取决于实施对象.对于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) 我将Python对象定义为"在任何深度都是不可变的"iff
例如((1, 2), (3, 4)),在任何深度都是不可变的,而((1, 2), [3, 4])不是(尽管后者,由于是一个元组,"名义上"是不可变的).
有没有合理的方法来测试Python对象是否"在任何深度都是不可变的"?
测试第一个条件相对容易(例如使用collections.Hashable类,忽略了不正确实现__hash__方法的可能性),但第二个条件更难以测试,因为"容器"对象的异质性,以及迭代他们的"内容"......
谢谢!
我有这样的事情:
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,那么我应该能够在字典中使用它.
所以现在我怀疑我打算做的事实际上是可行的,但是我根本无法使语法正确.
我正在尝试使用键创建一个字典作为我创建的结构,并将值作为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) 我遇到了很多在线示例,当他们尝试符合时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) 在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)
这在某种程度上是重复的,并且很明显有在更新另一个更新时忘记更新一个的风险。
是否有建议的方法一起实现这些方法?
在我提交雷达之前,只需与社区进行健全检查:
在.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
附加信息:
该文件表明:
==.字典键类型的哈希值类型必须是可散列的才能用作字典的键类型 - 也就是说,类型必须提供计算自身散列值的方法.散列值是一个Int值,是对于比较相等的所有对象中,相同的,使得如果一个== B,它遵循a.hashValue == b.hashValue.
所有斯威夫特的基本类型(如字符串,整数,双精度和布尔)的默认情况下可哈希的,而所有这些类型的可以作为一个字典的键.默认情况下,没有关联值的枚举成员值(如枚举中所述)也是可清除的.
注意您可以使用自己的自定义类型作为字典键类型,使其符合Swift标准库中的Hashable协议.符合所述哈希的协议类型必须提供一个gettable int属性称为散列值,并且还必须提供"等于"运算符(==)的实现.类型的hashValue属性返回的值在同一程序的不同执行或不同程序中不需要相同.有关符合协议的更多信息,请参阅协议.
我在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属性本身生成散列值.任何帮助深表感谢.
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) hashable ×10
swift ×8
protocols ×3
dictionary ×2
ios ×2
python ×2
equality ×1
equatable ×1
immutability ×1
nested ×1
objective-c ×1
struct ×1
swift3 ×1
type-erasure ×1
xcode ×1