我有foo: seq<int*int>
我想拆分元组,然后将结果存储到两个变量中,每个变量为seq<int>
我想知道是否有更好的方法来做到这一点,例如。
let item1, item2 = foo |> ?????
我目前的解决方案:
let item1 = foo |> Seq.map(fun (f1,_) -> f1)
let item2 = foo |> Seq.map(fun (_,f2) -> f2)
答案 0 :(得分:7)
可悲的是,虽然Lists(Seq.unzip
)和Arrays(List.unzip
)的等价物确实存在,但该语言中没有插入Array.unzip
函数。
有几种方法可以定义这样的函数,其中一种方法是:
let unzip sequence =
let (lstA, lstB) =
Seq.foldBack (fun (a,b) (accA, accB) ->
a::accA, b::accB) sequence ([],[])
(Seq.ofList lstA, Seq.ofList lstB)
或者,如果您不关心在列表之间来回切换,您可以这样做:
let item1, item2 =
let it1, it2 =
foo
|> List.ofSeq
|> List.unzip
(Seq.ofList it1, Seq.ofList it2)
答案 1 :(得分:3)
你想得到的是两个不同的序列,所以你找不到更漂亮的方法来做到这一点。你拥有的东西几乎已经足够了,但你可以通过使用fst
和snd
分别修饰元组的第一和第二项,并将两个表达式写在同一行上来缩短它:
let items1, items2 = foo |> Seq.map fst, foo |> Seq.map snd
答案 2 :(得分:3)
对于列表和数组,这些函数是内置的:
> [(1, "foo"); (2, "bar"); (3, "baz")] |> List.unzip;;
val it : int list * string list = ([1; 2; 3], ["foo"; "bar"; "baz"])
> [|(1, "foo"); (2, "bar"); (3, "baz")|] |> Array.unzip;;
val it : int [] * string [] = ([|1; 2; 3|], [|"foo"; "bar"; "baz"|])
但Seq
并不存在。
答案 3 :(得分:2)
要添加TheInnerLight的答案,official documentation告诉我们:
Seq.zip和Seq.zip3采用两个或三个序列并产生一系列元组。这些功能类似于列表可用的相应功能。没有相应的功能将一个序列分成两个或多个序列。 如果序列需要此功能,请将序列转换为列表并使用List.unzip 。
我的自发解决方案(类似于OP的方法)应该写:
let unzip sequence =
let source = Seq.cache sequence
Seq.map fst source, Seq.map snd source
(我在FSI中测试了1000000个元素,它也比我的计算机上的List.unzip方法慢一点)