我想制作hashset
(int*int)[]
,如下所示
let mySet = new HashSet<_>()
因为我认为array
和tuple
的默认比较器是HashIdentity.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
,而 list 是。{但是,默认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)
答案 0 :(得分:8)
我认为一个原因是Array是一个可变的和.NET兼容的类型。遵循.NET框架中默认的引用比较是有意义的。
您可以传递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)|]]
答案 1 :(得分:2)
查看Dictionary和HashSet类的文档。
<强> HashSet的强>
初始化一个空的HashSet类的新实例,并使用集合类型的默认相等比较器。
<强>词典强>
根据默认的相等比较器,Dictionary中的每个键都必须是唯一的。 Dictionary需要一个相等的实现来确定键是否相等。此构造函数使用默认的通用相等比较器EqualityComparer.Default。如果类型TKey实现System.IEquatable泛型接口,则默认的相等比较器使用该实现。或者,您可以使用接受比较器参数的构造函数指定IEqualityComparer泛型接口的实现。