I have a sequence with {"1";"a";"2";"b";"3";"c";...}
.
How can I transform this seq into {("1","a");("2","b");("3","c");...}
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
You might consider using LazyLists for this.
let (|Cons|Nil|) = LazyList.(|Cons|Nil|)
let paired items =
let step = function
| Cons(x, Cons(y, rest)) ->
Some((x, y), rest)
| _ ->
None
Seq.unfold step (LazyList.ofSeq items)
You can use pattern matching in the following way:
let list = ["1";"2";"3";"4";"5";"6"]
let rec convert l =
match l with
x :: y :: z -> (x,y) :: convert z
| x :: z -> (x,x) :: convert z
| [] -> []
let _ =
convert list
but you have to decide what to do if the list has an odd number of elements (in my solution a pair with same value is produced)