Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to "merge" multiple lists of the same length in F#?

I have a number of lists - each instance of which contains 9 floating point numbers. What I effectively need to do is produce one new list that takes the first element from each of my lists and adds them together as my first element, then add the second element from each list as my second element, etc.

So effectively, if my data looks something like this:

List1 = [a1; b1; c1; d1; e1; f1; g1; h1; i1]
List2 = [a2; b2; c2; d2; e2; f2; g2; h2; i2]
...
Listn = [an; bn; cn; dn; en; fn; gn; hn; in]

Then I need to produce a new list Listx such that

Listx = [a1 + a2 + ... + an; b1 + b2 + ... + bn; ... ]

The number of lists I will be merging will vary (sometimes I may only have a single list of 9 numbers, and sometimes more than 100 lists, always 9 elements long), so I was wondering if anybody's got any advice on a nice idiomatic way of doing this?

I did have a look at this question and this one but both appear to advocate an intermediate step of indexing my elements first and then using groupby. This bugs me because a) I get the feeling there might be a more elegant solution for my particular case and b) performance may be an issue later - I don't want to optimize prematurely, but I also don't want to shoot myself in the foot.

like image 278
Terence Lewis Avatar asked Feb 01 '12 19:02

Terence Lewis


2 Answers

Here is a solution which works on a list of lists with the same length:

let mapN f = function
   | []  -> []
   | xss -> List.reduce (List.map2 f) xss

let inline merge xss = mapN (+) xss

// Usage
let yss = List.init 1000 (fun i -> [i+1..i+9])
let ys = merge yss
like image 156
pad Avatar answered Oct 11 '22 14:10

pad


I'd go via something easier like a matrix:

let merge xss =
  let m = matrix xss
  List.map (m.Column >> Seq.sum) [0..m.NumCols-1]
like image 29
J D Avatar answered Oct 11 '22 15:10

J D