Hashable
クラス、構造体、または列挙型に適合させることは難しくありません。への準拠を明示的に宣言しHashable
、プロパティを定義するだけですhashValue: Int
。実際には、a == b then a.hashValue == b.hashValue というhashValue
1 つの単純な公理を満たす必要があります。
( に適合Hashable
させるには、型も にする必要がありますEquatable
。 の場合はCGPoint
、既にEquatable
です。)
CGPoint
準拠させる例Hashable
:
extension CGPoint: Hashable {
public var hashValue: Int {
//This expression can be any of the arbitrary expression which fulfills the axiom above.
return x.hashValue ^ y.hashValue
}
}
var pointDict: [CGPoint: String] = [
CGPoint(x: 1.0, y: 2.0): "PointA",
CGPoint(x: 3.0, y: 4.0): "PointB",
CGPoint(x: 5.0, y: 6.0): "PointC",
]
print(pointDict[CGPoint(x: 1.0, y: 2.0)]) //->Optional("PointA")
asには値CGPoint
が含まれてCGFloat
いるため、CGPoint
as Dictionary の Key は、2 進浮動小数点システムの計算エラーに基づいて予期しない動作を引き起こす可能性があります。特に注意して使用する必要があります。
添加
計算エラーの問題を回避し、構造体に のみを含めるInt
ことができる場合は、独自の構造体を定義して、次のように準拠させることができますHashable
。
struct MyPoint {
var x: Int
var y: Int
}
extension MyPoint: Hashable {
public var hashValue: Int {
return x.hashValue ^ y.hashValue
}
public static func == (lhs: MyPoint, rhs: MyPoint) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
var myPointDict: [MyPoint: String] = [
MyPoint(x: 1, y: 2): "MyPointA",
MyPoint(x: 3, y: 4): "MyPointB",
MyPoint(x: 5, y: 6): "MyPointC",
]
print(myPointDict[MyPoint(x: 1, y: 2)]) //->Optional("MyPointA")
上記のコードほど難しくはありません。もう 1 つ必要なのは==
、構造体の演算子を定義することだけです。ぜひお試しください。