Dictionary Seq.groupBy:保留原始顺序

Dictionary Seq.groupBy:保留原始顺序,dictionary,f#,enumeration,Dictionary,F#,Enumeration,Dictionary–和扩展名为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 <>

Dictionary
–和扩展名为
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)

我是哑巴还是这个问题有点让人困惑?如果你需要保证,我想你要么自己实现,要么使用(一些)
Seq.order
calls@ChaosPandion:我不确定。:-)@卡斯滕克尼:是的,很好。这是显而易见的方法。我在这里寻找创造力。我知道它不是内置的…这就是问题的动力。在一般情况下,如果键与源序列中的元素(不一定)相同,并且键可能会重复,那么保持原始顺序意味着什么?你是担心小组本身的顺序,小组内部的顺序,还是两者都担心?啊!15秒后,使用完全相同的代码(不仅在语义上相同,而且在字面上也相同!),文档不能保证这一点,但我们知道
Seq.groupBy
保留每个组中的值顺序,因此您的第一个函数应该做到这一点。我为我的问题添加了另一个可能的解决方案。它的性能与您的类似。你知道它和你的有什么实际的区别吗?函数组合真的让我头疼:)我花了5分钟才弄明白snd>>Seq.map fst>>Seq.min试图实现什么。