我有以下代码:
open System
open System.Linq
type Child = {
id: Guid
name: int
parent: Guid
}
type Parent = {
id: Guid
name: int
children: seq<Guid>
}
let makeChild name parentId =
{
Child.id = Guid.NewGuid()
name = name
parent = parentId
}
let makeParent (group: IGrouping<int, int>) =
let id = Guid.NewGuid()
let children = group |> Seq.map (fun x -> makeChild x id)
let ids = children |> Seq.map (fun x -> x.id)
({
Parent.id = id
name = group.Key
children = ids
}, children)
let makeAll (groups: seq<IGrouping<int, int>>) =
let result = groups |> Seq.map (fun x -> makeParent x)
let children = result |> Seq.map (fun x -> snd x) |> Seq.concat
let parents = result |> Seq.map (fun x -> fst x)
(parents, children)
(我接受IGrouping<int, int>
而不是seq<int * seq<int>>
,因为此代码需要与C#互操作。)
但是,当我使用以下内容运行时:
let parents, children = makeAll(Enumerable.Range(0, 100).GroupBy(fun x -> x % 10))
然后没有孩子。[i] .parent guids与父母相关。[j] .children。[k] guids for i,j,k。
为什么不是这样?我怎么能这样做呢?
答案 0 :(得分:3)
没有对此进行测试,但似乎问题在于您将结果seq两次枚举,一次在let children
,一次在let parents
行。由于guid生成具有副作用,因此每个枚举都会得到两个不同的结果。
如果您在let result
行缓存seq(或通过将其转换为数组或同一行中的列表来实现它),您应该得到您正在寻找的内容:
let result = groups |> Seq.map (fun x -> makeParent x) |> Seq.cache
makeParent
函数中的相同内容。 ids
seq也需要缓存。
&#34;陷阱&#34;这就是为什么我发现最好在函数或接口的边界上使用具体的集合类型而不是seqs。如果您正在寻找懒惰,可以使用Lazy类型使其明确。