How to get pairs of consecutive values ​​from F # Seq

I have a sequence with {"1";"a";"2";"b";"3";"c";...} .

How can I convert this seq to {("1","a");("2","b");("3","c");...}

+6
source share
6 answers

This is too smart a solution:

 let s = ["1";"a";"2";"b";"3";"c"] let pairs s = s |> Seq.pairwise |> Seq.mapi (fun ix -> i%2=0, x) |> Seq.filter fst |> Seq.map snd printfn "%A" (pairs s) 
+15
source

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 # Seq.pairwise source code 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 } 
+10
source

Since F # 4.0, now you can 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) 
+2
source

You can use 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) 
+1
source

You can use pattern matching as follows:

 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 the same value is created)

0
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 ix -> if i%2=0 then Some(x) else None) |> Seq.choose id 

And here is 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 
0
source

All Articles