Steven Proctor发布了Ruby Enumerable#group_by
的一个例子:
["tar", "rat", "bar", "rob", "art", "orb"].group_by {|word| word.chars.sort}
# => {["a", "r", "t"]=>["tar", "rat", "art"],
# ["a", "b", "r"]=>["bar"],
# ["b", "o", "r"]=>["rob", "orb"]}
我决定在F#做同样的事情:
let grouped = seq ["tar";"rat";"bar";"rob";"art";"orb"]
|> Seq.groupBy (fun word -> word |> Seq.sort)
...但我没有得到与Ruby程序相同的结果:
seq
[(seq ['a'; 'r'; 't'], seq ["tar"]);
(seq ['a'; 'r'; 't'], seq ["rat"]);
(seq ['a'; 'b'; 'r'], seq ["bar"]);
(seq ['b'; 'o'; 'r'], seq ["rob"]);
(seq ['a'; 'r'; 't'], seq ["art"]);
(seq ['b'; 'o'; 'r'], seq ["orb"])]
为什么Seq.groupBy
不是,组合?根据FSI,实际上两个等价序列是相等的:
> let a = seq ['a'; 'r'; 't'];;
> let b = seq ['a'; 'r'; 't'];;
> a = b;;
// val it : bool = true
为什么Seq.groupBy
不会返回以下内容?
seq
[(seq ['a'; 'r'; 't'], seq ["tar"; "rat"; "art"]);
(seq ['a'; 'b'; 'r'], seq ["bar"]);
(seq ['b'; 'o'; 'r'], seq ["rob"; "orb"])]
答案 0 :(得分:2)
如果你试图检查fsi这个平等:
seq { yield 1; yield 2 } = seq { yield 1; yield 2 }
你会得到假的。列表的比较正如您所期望的那样工作。
您需要做的就是将序列转换为列表或保留数组
|> Seq.groupBy (fun word -> word |> Seq.sort |> List.ofSeq)
答案 1 :(得分:2)
Seq.sort
返回't seq
类型的值,这是IEnumerable<'t>
的同义词。现在,IEnumerable<'t>
不是结构上可比较的类型,因此对来自Seq.sort
的调用产生的结果无法匹配和分组。
您可以添加|> List.ofSeq
或|> Array.ofSeq
以将't seq'
转换为't list
或't []
,这两者在结构上具有可比性。
答案 2 :(得分:2)
只需添加Seq.toList
:
let grouped =
seq ["tar";"rat";"bar";"rob";"art";"orb"]
|> Seq.groupBy (fun word -> word |> Seq.sort |> Seq.toList)
产地:
> grouped |> Seq.toList;;
val it : (char list * seq<string>) list =
[(['a'; 'r'; 't'], seq ["tar"; "rat"; "art"]);
(['a'; 'b'; 'r'], seq ["bar"]);
(['b'; 'o'; 'r'], seq ["rob"; "orb"])]
它在OP中没有工作的原因是因为Seq.sort
返回char seq
,这是IEnumerable<char>
的别名 - 对象。两个对象彼此不相等,除非它们引用相同的地址;他们有参考平等。
通过将它们转换为列表,您可以获得预期的结构平等。