I have a sequence with {"1";"a";"2";"b";"3";"c";...}
.
How can I transform this seq into {("1","a");("2","b");("3","c");...}
Here is a much-too-clever solution:
let s = ["1";"a";"2";"b";"3";"c"]
let pairs s =
s |> Seq.pairwise
|> Seq.mapi (fun i x -> i%2=0, x)
|> Seq.filter fst
|> Seq.map snd
printfn "%A" (pairs s)
Enumerators are not always evil.
let pairs (source: seq<_>) =
seq {
use iter = source.GetEnumerator()
while iter.MoveNext() do
let first = iter.Current
if iter.MoveNext() then
let second = iter.Current
yield (first, second)
}
Here is the F# source code of Seq.pairwise
taken from FSharp.Core/seq.fs
[<CompiledName("Pairwise")>]
let pairwise (source: seq<'T>) = //'
checkNonNull "source" source
seq { use ie = source.GetEnumerator()
if ie.MoveNext() then
let iref = ref ie.Current
while ie.MoveNext() do
let j = ie.Current
yield (!iref, j)
iref := j }
Since F# 4.0, you can now use chunkBySize
let source = seq ["1";"a";"2";"b";"3";"c"]
let pairs source =
source
|> Seq.chunkBySize 2
|> Seq.map (fun a -> a.[0], a.[1])
;;
printfn "%A" (pairs source)
Here's a variation on @Brian's solution:
["1";"a";"2";"b";"3";"c";"4";"d";"5";"e";"6";"f"]
|> Seq.pairwise
|> Seq.mapi (fun i x -> if i%2=0 then Some(x) else None)
|> Seq.choose id
And here's a brain-melter using Seq.scan:
["1";"a";"2";"b";"3";"c";"4";"d";"5";"e";"6";"f"]
|> Seq.scan (fun ((i,prev),_) n -> match prev with
| Some(n') when i%2=0 -> ((i+1,Some(n)), Some(n',n))
| _ -> ((i+1,Some(n)), None))
((-1,None), None)
|> Seq.choose snd
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