3

hashsetのを作りたい(int*int)[]ので、次のように

let mySet = new HashSet<_>()

arrayとのデフォルトの比較子だと思ったので、それtupleHashIdentity.Structural私のニーズを自動的に満たします。

ただし、機能しません。これが私の実験です:

let mySet = new HashSet<_>()
let a = [|1;2|]
let b = [|1;2|]
let c = compare a b
mySet.Add(a)
mySet.Add(b)

val a : int [] = [|1; 2|]
val b : int [] = [|1; 2|]
val c : int = 0
val it : HashSet<int []> = seq [[|1; 2|]; [|1; 2|]]

let mySet = new HashSet<_>()
let a = [1;2]
let b = [1;2]
let c = compare a b
mySet.Add(a)
mySet.Add(b)

val a : int list = [1; 2]
val b : int list = [1; 2]
val c : int = 0
val it : HashSet<int list> = seq [[1; 2]]

ご覧のとおり、配列のデフォルトIEqualityComparerはでありませんHashIdentity.Structuralが、リストはです。ただし、デフォルトIComparerは両方の構造です。

それは少し奇妙です、なぜですか?また、IEqualityComparerとのデフォルトの構造比較を使用してハッシュセットtupleのを作成する方法array

C#で手動で行う方法は知っていますが、F#を学び始めたばかりなので、誰か助けてもらえますか?

次のコードは私の努力です:

let a = [|(1,2);(2,3)|]
let b = [|(1,2);(2,3)|]

type MyEqualityComparer() =
    interface IEqualityComparer<(int*int)[]> with
        member this.Equals (a,b) = (Array.forall2 (=) a b)
        member this.GetHashCode (a) = hash (a |> Array.map hash)
4

2 に答える 2

8

理由の1つは、Arrayが変更可能で.NET互換のタイプであるためだと思います。.NETFrameworkのデフォルトである参照比較に従うことは理にかなっています。

HashIdentity.Structural引数として渡すことができます。次の例では、配列とタプルの構造比較を使用しています。

let mySet = HashSet(HashIdentity.Structural)
let a = [|(1, 2)|]
let b = [|(1, 2)|]
mySet.Add(a)
mySet.Add(b)
// val it : HashSet<(int * int) []> = seq [[|(1, 2)|]]
于 2012-09-25T17:19:31.303 に答える
2

DictionaryクラスとHashSetクラスのドキュメントを確認してください。

HashSet

空で、セットタイプのデフォルトの等式比較子を使用するHashSetクラスの新しいインスタンスを初期化します。

辞書

ディクショナリ内のすべてのキーは、デフォルトの等式比較器に従って一意である必要があります。ディクショナリでは、キーが等しいかどうかを判断するために等式の実装が必要です。このコンストラクターは、デフォルトのジェネリック等式比較子EqualityComparer.Defaultを使用します。タイプTKeyがSystem.IEquatableジェネリックインターフェイスを実装している場合、デフォルトの等式比較プログラムはその実装を使用します。または、比較パラメーターを受け入れるコンストラクターを使用して、IEqualityComparerジェネリックインターフェイスの実装を指定することもできます。

于 2012-09-25T16:27:03.970 に答える