# Pair up elements of a sequence without overlap

I have a sequence (in this case actually an array) like this:

[| 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]


And want to produce a sequence of pairs like this:

[(1, 2); (3, 4); (5, 6); (7, 8); ...]


The following code works, but I can't help feeling that it's a lot of code. Is there a shorter, more idiomatic or more elegant way to do this.

[| 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
|> Seq.pairwise
|> Seq.mapi (fun i t -> (i, t))
|> Seq.filter (fun (i, t) -> i % 2 = 0)
|> Seq.map (fun (i, t) -> t)


Here's another way:

[| 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
|> Seq.chunkBySize 2
|> Seq.choose (function [|x; y|] -> Some (x, y) | _ -> None)


So, chunkBySize will create a sequence like seq [ [|1; 2|]; [|3; 4|]; .. ]

Then choose will try to match each element of the sequence with an array of two elements, everything else will be filtered out, which accounts for a trailing array of a single element if the input length is not even.

It could be even shorter by changing the last line to:

|> Seq.collect Array.pairwise


Which would map pairwise to the each element, transforming for instance [|1;2|] to [|(1;2)|] and it will return [||] when there are less than two elements. So this will return a sequence of an array but since I'm using collect it will concatenate all elements. Since single elements were transformed to empty arrays it will concatenate nothing in those cases, if you think about it this is similar to the mechanics of choose.

• Ooh, I didn't know about Seq.chunkBySize! That's great. I presume you used Seq.choose to avoid a 1-tuple at the end in case the input had an odd number of elements? – Avrohom Yisroel Apr 19 '18 at 16:45
• Obviously this code is shorter but could you provide a little explanation of why it is simpler, for the OP and future readers? – Sᴀᴍ Onᴇᴌᴀ Apr 19 '18 at 16:52
• Done, hope it helps ! – Gus Apr 19 '18 at 17:14