我想对一个序列进行分组,然后在组中的每个元素的第一个出现。当我尝试这个Seq.groupBy是否在组内保持顺序?
Seq.groupBy f inSeq
|> Seq.map (fun (k,s) -> (k,s|>Seq.take 1|>Seq.exactlyOne))
我发现,有时候我得到个不同的元素。这是预期的吗?
我想对一个序列进行分组,然后在组中的每个元素的第一个出现。当我尝试这个Seq.groupBy是否在组内保持顺序?
Seq.groupBy f inSeq
|> Seq.map (fun (k,s) -> (k,s|>Seq.take 1|>Seq.exactlyOne))
我发现,有时候我得到个不同的元素。这是预期的吗?
综观source of the groupBy
implementation - 这里的相关位:
// Build the groupings
seq |> iter (fun v ->
let safeKey = keyf v
let mutable prev = Unchecked.defaultof<_>
match dict.TryGetValue (safeKey, &prev) with
| true -> prev.Add v
| false ->
let prev = ResizeArray()
dict.[safeKey] <- prev
prev.Add v)
它通过源阵列迭代,并添加值的键对应的列表。子序列的顺序直接受输入序列的顺序影响。对于相同的输入序列,我们可以预期groupBy
返回相同的输出序列。这是测试如何编码为groupBy
。
如果您看到结果序列的变化,请检查输入序列。
谢谢,这是我的预期,但对于某些原因我收到了不同的东西。不幸的是,现在我不能重现这个问题。 –
@RobertSim相反,它一定是“我的机器上的作品”的例子。 – Asti
是的,这是预期的。序列(seq
)不保证是pure。您可以定义一个序列,每次遍历它们时都会产生不同的值。如果您拨打Seq.take 1
两次,您可以得到不同的结果。
考虑,作为一个例子,这个序列:
open System
let r = Random()
let s = seq { yield r.Next(0, 9) }
如果调用该Seq.take 1
,你可能会得到不同的结果:
> s |> Seq.take 1;;
val it : seq<int> = seq [4]
> s |> Seq.take 1;;
val it : seq<int> = seq [1]
使用Seq.head
是不会帮你要么:
> s |> Seq.head;;
val it : int = 2
> s |> Seq.head;;
val it : int = 6
如果要保证确定性b ehaviour,请改用List
。
......或者在某些情况下,可以使用'Seq.cache'来'固定'seq'(但关闭的行重新建模事物,因为它们应该保留) –
是的,我应该在第二行使用Seq.head,但我想分享我正在逐字处理的代码。 :) –
当这种情况发生时,你能隔离这些情况吗? –