9
$\begingroup$

Suppose I have a list of lists with different lengths, sorted from longest to shortest

 myLists = Sort[Table[RandomReal[1, RandomInteger[50]], {25}], Length@#1 > Length@#2 &];

I would like to add up all the first elements, then all the second, and so on elements for each list that has the required number of elements.

For example if my lists are

{
 {1,2,3},
 {4,5},
 {6}
}

Then I want to return

{11,7,3}

The following code performs this using For loops, but I am trying to figure out a better way of doing this.

sums = Table[0, {Max[Length /@ a]}];
(* For each row element up to the length of the longest list *)
For[j = 1, j <= Max[ Length /@ a], j++,
(* For each list *)
     For[k = 1, k <= Length[a], k++,
(* Add the element to the correct sum if it exists *)
            If[Length[a[[k]]] >= j,
                 sums[[j]] = sums[[j]] + a[[k, j]],
                 Break[]
              ]
        ]
   ]
$\endgroup$
  • 1
    $\begingroup$ wouldn't it be easier to simply pad every thing to the right length with 0 and then add? Or are zeros appropriate values that can exist in your ragged length list? $\endgroup$ – tkott Nov 15 '12 at 20:09
  • 3
    $\begingroup$ We have just had a question that requires a similar solution. One way is to use Flatten to transpose a 'ragged' array. For example Total /@ Flatten[list, {2}] => {11, 7, 3} $\endgroup$ – user1066 Nov 15 '12 at 20:14
  • $\begingroup$ Thanks guys, looks like Total /@ Flatten[list,{2}] will do the trick. So much simplier! $\endgroup$ – David Slater Nov 15 '12 at 20:30
9
$\begingroup$

The second argument of Flatten can be used to transpose ragged lists (also see this answer by Leonid). With this, you can use the second argument of Total to sum each sublist. The following is similar to my comment here:

list = {{1, 2, 3}, {4, 5}, {6}} 
list ~Flatten~ {2} ~Total~ {2}
(* {11, 7, 3} *)
$\endgroup$
3
$\begingroup$

One solution is to use PadRight[] to make a square array (with for example Empty to fill in the blank spots), then Transpose[] it and delete all the Empty's. Finally, you can Total[] all the rows.

Random data:

a = RandomInteger[{0, 20}, #] & /@ Reverse[Range[10]];

Then:

Map[Total, 
 DeleteCases[#, x_ /; x === Empty] & /@ 
  Transpose[PadRight[a, {10, 10}, Empty]]]

It's a bit of a workaround, but it does the trick.

$\endgroup$
2
$\begingroup$

As A. Goossens mentions, one can use PadRight[] as an alternative, though in fact one can leverage the fact that

PadRight[list] pads a ragged array list with zeros to make it full.

so:

Total[PadRight[{{a, b}, {c, d, e, f}, {g, h, i}}]]
   {a + c + g, b + d + h, e + i, f}
$\endgroup$
  • $\begingroup$ I explicity used Empty so the data stays the same even if there are already zeros in it. For the solution it doesn't make any difference, that's true. $\endgroup$ – Aart Goossens Nov 16 '12 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.