2016-12-21 4 views
3

することができ、私はキーとして非常に単純なタプルを使用したい:は、単純なタプルがハッシュ可能に準拠して作成しますので、辞書のキー

(Int, Int) 

辞書のキーは、ハッシュ可能にする必要があります。私は学んだ。

しかし、このシンプルなタプルHashableをどうやって作っているのか分からず、いつもプロトコル適合に苦しんでいます。

さらに深く、CGPointは私の問題を解決します。この形式でもかまいませんが、ハッシュ可能ではありません。

CGPointをハッシュ可能に拡張することはできますか?もしそうなら、どうですか?

EDIT:CGPointの選択肢のIntバリアントの画像です。

enter image description here

+0

関連項目:[スイフトでは辞書のキーとしてタプルを使用できますか?](http://stackoverflow.com/q/24131323/2976878) – Hamish

答えて

6

Hashableに準拠して作成クラス、構造体や列挙型のために難しいことではありません。 適合性を明示的に宣言してHashableに設定し、プロパティーhashValue: Intを定義するだけです。実際には、hashValueは、a == bならばahashValue == b.hashValueならばという簡潔な公理を実現する必要があります。

Hashableに準拠するために、あなたはまた、タイプEquatableをする必要がありCGPointの場合、それはすでにEquatableである。。)

例をHashableに準拠CGPointを作るために:

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") 

として、 CGPointにはCGFloatの値が含まれているため、Dictionary of KeyとしてのCGPointは、バイナリ浮動小数点システムの計算エラーに基づいて予期しない動作を引き起こす可能性があります。あなたはそれに余分な注意を払って使用する必要があります。


ADDITION

あなたには、いくつかの計算誤差の問題を回避したいと構造のみ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つのことは、構造体に対して==演算子を定義することです。試してみてください。

+0

優れています。浮動体については、Integersに基づいたCGPointバリアントを強制的に使用できますか? – Confused

+0

質問に画像を追加しました。ここにコメントを追加できません – Confused

+0

'CGPoint'の' Int'を使ってイニシャライザを使用しても、値は内部的に 'CGFloat'に変換されます。 CGPointバリアント_を持つ独自の構造体を意味する場合は、それを行うことができます。 'struct MyPoint:Hashable {...}'のようなものを書くことができます。ちょうど 'hashValue'プロパティと' == '演算子の両方を定義する必要があります。 – OOPer

関連する問題