Seq.groupBy:保留原始顺序
Dictionary<_,_>
-and Seq.groupBy
通过伸展出现枚举元素中的插入顺序,然而顺序是正式未定义(见this question)。Seq.groupBy:保留原始顺序
下面是一些代码来演示:
let groupByPreservesOrder l =
let l2 =
l
|> Seq.groupBy id
|> Seq.map fst
|> Seq.toList
(l = l2)
let l = List.init 1000 (fun i ->
if i % 2 <> 0 then -(i) else i/2)
groupByPreservesOrder l //true
我需要一组功能保证此行为。什么是最好的(认真,高效,惯用,...)的方式去做呢?
编辑
下面是做这件事:
let groupByStable f items =
let items = items |> Seq.map (fun x -> f x, x) |> Seq.toList
let d = items |> Seq.groupBy fst |> dict
items
|> Seq.distinctBy fst
|> Seq.map (fun (k, _) -> k, Seq.map snd d.[k])
如果你想确保序列是由每个键的首次亮相排序,那么这里做到这一点的一种方法:
let groupByOP f s =
s
|> Seq.mapi (fun i x -> i,x)
|> Seq.groupBy (snd >> f)
|> Seq.sortBy (snd >> Seq.map fst >> Seq.min)
|> Seq.map (fun (k,vs) -> k, vs |> Seq.map snd)
如果你还想每个组按初始放置排序,那么我认为这样的事情应该工作:
let groupByOP f s =
s
|> Seq.mapi (fun i x -> i,x)
|> Seq.groupBy (snd >> f)
|> Seq.map (fun (k,vs) -> k, vs |> Seq.sortBy fst)
|> Seq.sortBy (snd >> Seq.head >> fst)
|> Seq.map (fun (k,vs) -> k, vs |> Seq.map snd)
Doh! 15秒后**完全相同的代码(并且不仅仅是语义相同,而是字面相同!) – 2012-03-22 15:58:08
文档不能保证它,但我们知道'Seq.groupBy'保留了每个组内的值的顺序,所以你的第一个功能应该做的伎俩。我添加了另一个可能的解决方案,它的表现与你的相似。你知道它与你的实际区别吗? – Daniel 2012-03-22 18:29:28
功能组合真的让我头疼:)我花了5分钟来找出什么snd >> Seq.map fst >> Seq.min试图完成。 – 2015-12-01 00:03:40
我是哑巴还是这个问题有点混乱? – ChaosPandion 2012-03-22 15:27:55
如果你需要它*保证*我想你要么必须自己实施或使用(一些)'Seq.order'调用 – Carsten 2012-03-22 15:29:16
@ChaosPandion:我不确定。 :-) – Daniel 2012-03-22 15:30:51