I have a function witch is written in an imperative style and cant get my head around on how to convert it to a more robust functional approach.
The function takes a seq of strings and returns a seq of tuples where each tuple consists of the 2,7,12,.. and 5,10,15,.. item from the input.
Example:
Input = { “Lorem”, “ipsum”, “dolor”, “set”, “amet”, “consectetuer”, “adipiscing”, “elit”, “Aenean”, “commodo”, “ligula”, “eget”, “dolor”, “Aenean”, “massa” }
Ouput = { (“ipsum”, “amet”), (“adipiscing”, “commodo”), (“eget”, “massa”) }
let convert (input : seq<string>) : seq<(string * string)> =
let enum = input.GetEnumerator()
let index = ref 0
let first = ref ""
let second = ref ""
seq {
while enum.MoveNext() do
let modIndex = !index % 5
index := !index + 1
if (modIndex % 2 = 0 && !first = "") then first := enum.Current
if (modIndex % 5 = 0 && !second = "") then second := enum.Current
if modIndex = 0 then
let result = (!first, !second)
first := ""
second := ""
yield result
}
Any help or tip for a starting point is appreciated.
I do not completely understand the behaviour you want – what is the algorithm for generating indices that you want to pair? Anyway, one nice functional solution is to take the elements you want to pair separately and then combine them using
Seq.zip.You can use
Seq.mapito add indices to the values and then useSeq.chooseto get the values with the right index (and skip all other values). For hardcoded indices, you can write something like:I used your numbers -1 because the indices are from 0 – so the above gives you the results you wanted. The second series looks like multiples of 5, so perhaps you wanted
i%5 = 4to generate second elements:I still don’t see the general mechanism for generating the first elements though!
EDIT One more idea – is the first sequence generated by
i*5 + 2and the second byi*5? In that case, your example is wrong, but you could write it like this:… or if you want to make the code shroter, you can refactor: