2016-08-22 9 views
10

は、私は何もすることができstructを、持っていると言いますか?構造タイプのスウィフト設定

let points: Set<Cube> = Set() 
// Type ‘Cube’ does not conform to protocol ‘Hashable’ 

ハッシュ可能を実装する方法はすぐにはわかりません。私が読んだところから、私はハッシュ関数を作る必要がありますが、それは構造体にあるプロパティの量では簡単には見えません。

func ==(lhs: Cube, rhs: Cube) -> Bool { 
    return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.width == rhs.width 
} 

Hashableプロトコルのみがいる必要があります。あなたが一意にキューブを識別するすべてのプロパティ を使用して、2つの値を比較==オペレータは 実装しなければならないように、すべての

答えて

13

まず、Hashableは、Equatable延び

x == yx.hashValue == y.hashValue

ので

var hashValue: Int { 
    return 0 
} 

は、有効な(と作業)の実装になります。ただし、 は、すべてのオブジェクトをセット(または辞書)の同じハッシュバケットに入れます。 は有効ではありません。それがオーバーフローすることはできませんので、より高度な実装は、例えばここで

struct Cube: Hashable { 
    var x: Int 
    var y: Int 
    var z: Int 
    var width: Int 

    var hashValue: Int { 
     return x.hashValue^y.hashValue^z.hashValue^width.hashValue 
    } 
} 

のために、「XOR」演算子^が選択されています。 「オーバーフロー演算子」&+を使用することもできます。

より洗練されたハッシュ関数は、 の異なる値をよりよく区別することができるため、設定操作が高速になります。 一方、ハッシュ関数自身 の計算は遅くなります。したがって、私は "より良い"ハッシュ関数 を探します。ただし、設定された操作がプログラムのパフォーマンスのボトルネックになっている場合に限ります。

+0

良い説明!私を捨てていたのは、hashValueがすべての構造体に対して完全に一意でなければならないと思ったということです。主に最適化のように見えます!ありがとう! –

+1

@JacobParker:構造体には2^256の異なる値があり、ハッシュ値は2^64しかないため、*ユニークではありません(ハッシュ値は通常はありません)。もちろん、それを独自のものにすることもできます。たとえば、すべてのコンポーネントが16ビットに制限されている場合、 '(x << 48)&+(y << 32)&+(z << 16)&+ width」となります。 –

7

Hashableプロトコルの実装には2つのものがあります。最初にhashValueを実装し、2つ目は等価演算子を実装しています。

Hashableプロトコルの重要な部分は、等価演算子です。これは、trueを返す方法で実装しなければならず、2つの構造に同じ値が含まれている場合にのみ実装する必要があります。

一方、同じ構造体が常に同じ値を返す限り、hashValue実装は文字通り何かを返すことができます。

hashValueが影響を与えるのは、値を追加または参照するときに最初に実行されるコードがhashValueなので、コードがどのくらい速く動作するかだけです。 hashValueが2つの構造体で同じ値を返す場合、それらの間の等価性は、そうでなければスキップされる等価演算子を呼び出すことによって決定されます。

struct Cube: Hashable { 

    // satisfy Hashable requirement 
    var hashValue: Int { 
     get { 
      // you can return any integer here 
      return x &+ y &+ z &+... 
      // or even the same one for all structs 
      return 0 
     } 
    } 
} 

// satisfy Equatable requirement 
func ==(lhs: Cube, rhs: Cube) -> Bool { 
    return lhs.x == rhs.x && lhs.y == rhs.y ..... 
} 
+1

備考: 'x + y + z'はオーバーフローする可能性があり、実行時エラーが発生します。 (+1)しかし、良い説明! –

+0

@ MartinsRありがとう、私はコードを修正しました。 –

関連する問題