I have a foo: seq<int*int>
I want to split the tupled items and then store the results to two variables, each a seq<int>
I was wondering if there was a prettier way to do this, e.g.
let item1, item2 = foo |> ?????
My current solution:
let item1 = foo |> Seq.map(fun (f1,_) -> f1)
let item2 = foo |> Seq.map(fun (_,f2) -> f2)
Sadly, there is no drop-in Seq.unzip
function included in the language, although equivalents for Lists (List.unzip
) and Arrays (Array.unzip
) do exist.
There are a few ways of defining such a function, one method is this:
let unzip sequence =
let (lstA, lstB) =
Seq.foldBack (fun (a,b) (accA, accB) ->
a::accA, b::accB) sequence ([],[])
(Seq.ofList lstA, Seq.ofList lstB)
Alternatively, if you don't care about switching back and forth between list, you can just do:
let item1, item2 =
let it1, it2 =
foo
|> List.ofSeq
|> List.unzip
(Seq.ofList it1, Seq.ofList it2)
What you want to get are two different sequences, so you won't find a much prettier way to do this. What you have is almost sufficient, but you can make it a bit shorter by using fst
and snd
for teasing first and second items of the tuples respectively, and writing both expression on the same line:
let items1, items2 = foo |> Seq.map fst, foo |> Seq.map snd
For lists and arrays, these functions are built-in:
> [(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"|])
It doesn't exist for Seq
, though.
To add on TheInnerLight's answer, the official documentation tells us that :
Seq.zip and Seq.zip3 take two or three sequences and produce a sequence of tuples. These functions are like the corresponding functions available for lists. There is no corresponding functionality to separate one sequence into two or more sequences. If you need this functionality for a sequence, convert the sequence to a list and use List.unzip.
My spontaneous solution (similar to the OP's approach) would have been to write :
let unzip sequence =
let source = Seq.cache sequence
Seq.map fst source, Seq.map snd source
(I tested it in FSI for 1000000 elements and it is also a bit slower than the List.unzip approach on my computeur)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With