4
$\begingroup$

Lets say I have the following input:

rn={
 {1, 1.1, 1.5},
 {5, 6, 6.1, 7},
 {8, 8, 12, 12, 12.5, 13}
}

This input has the dimensions of {3, 4, 6}.

I want to get each of the elements from each of the three lists, and add them to each of the elements of another list, for all possibilities, such as I would get a list that is 3 * 4 * 6 = 72 long.

I know that I can do this manually such that:

{
 rn[[1, 1]] + rn[[2, 1]] + rn[[3, 1]],
 rn[[1, 1]] + rn[[2, 1]] + rn[[3, 2]],
 rn[[1, 1]] + rn[[2, 1]] + rn[[3, 3]],
 rn[[1, 1]] + rn[[2, 1]] + rn[[3, 4]],
 rn[[1, 1]] + rn[[2, 1]] + rn[[3, 5]],
 rn[[1, 1]] + rn[[2, 1]] + rn[[3, 6]],
 rn[[1, 1]] + rn[[2, 2]] + rn[[3, 1]],
 rn[[1, 1]] + rn[[2, 2]] + rn[[3, 2]],
 rn[[1, 1]] + rn[[2, 2]] + rn[[3, 3]],
 rn[[1, 1]] + rn[[2, 2]] + rn[[3, 4]],
 rn[[1, 1]] + rn[[2, 2]] + rn[[3, 5]],
 rn[[1, 1]] + rn[[2, 2]] + rn[[3, 6]],
 rn[[1, 1]] + rn[[2, 3]] + rn[[3, 1]],
 rn[[1, 1]] + rn[[2, 3]] + rn[[3, 2]],
 rn[[1, 1]] + rn[[2, 3]] + rn[[3, 3]],
 rn[[1, 1]] + rn[[2, 3]] + rn[[3, 4]],
 rn[[1, 1]] + rn[[2, 3]] + rn[[3, 5]],
 rn[[1, 1]] + rn[[2, 3]] + rn[[3, 6]],
 rn[[1, 1]] + rn[[2, 4]] + rn[[3, 1]],
 rn[[1, 1]] + rn[[2, 4]] + rn[[3, 2]],
 rn[[1, 1]] + rn[[2, 4]] + rn[[3, 3]],
 rn[[1, 1]] + rn[[2, 4]] + rn[[3, 4]],
 rn[[1, 1]] + rn[[2, 4]] + rn[[3, 5]],
 rn[[1, 1]] + rn[[2, 4]] + rn[[3, 6]],
 rn[[1, 2]] + rn[[2, 1]] + rn[[3, 1]],
 rn[[1, 2]] + rn[[2, 1]] + rn[[3, 2]],
 rn[[1, 2]] + rn[[2, 1]] + rn[[3, 3]],
 rn[[1, 2]] + rn[[2, 1]] + rn[[3, 4]],
 rn[[1, 2]] + rn[[2, 1]] + rn[[3, 5]],
 rn[[1, 2]] + rn[[2, 1]] + rn[[3, 6]],
 rn[[1, 2]] + rn[[2, 2]] + rn[[3, 1]],
 rn[[1, 2]] + rn[[2, 2]] + rn[[3, 2]],
 rn[[1, 2]] + rn[[2, 2]] + rn[[3, 3]],
 rn[[1, 2]] + rn[[2, 2]] + rn[[3, 4]],
 rn[[1, 2]] + rn[[2, 2]] + rn[[3, 5]],
 rn[[1, 2]] + rn[[2, 2]] + rn[[3, 6]],
 rn[[1, 2]] + rn[[2, 3]] + rn[[3, 1]],
 rn[[1, 2]] + rn[[2, 3]] + rn[[3, 2]],
 rn[[1, 2]] + rn[[2, 3]] + rn[[3, 3]],
 rn[[1, 2]] + rn[[2, 3]] + rn[[3, 4]],
 rn[[1, 2]] + rn[[2, 3]] + rn[[3, 5]],
 rn[[1, 2]] + rn[[2, 3]] + rn[[3, 6]],
 rn[[1, 2]] + rn[[2, 4]] + rn[[3, 1]],
 rn[[1, 2]] + rn[[2, 4]] + rn[[3, 2]],
 rn[[1, 2]] + rn[[2, 4]] + rn[[3, 3]],
 rn[[1, 2]] + rn[[2, 4]] + rn[[3, 4]],
 rn[[1, 2]] + rn[[2, 4]] + rn[[3, 5]],
 rn[[1, 2]] + rn[[2, 4]] + rn[[3, 6]],
 rn[[1, 3]] + rn[[2, 1]] + rn[[3, 1]],
 rn[[1, 3]] + rn[[2, 1]] + rn[[3, 2]],
 rn[[1, 3]] + rn[[2, 1]] + rn[[3, 3]],
 rn[[1, 3]] + rn[[2, 1]] + rn[[3, 4]],
 rn[[1, 3]] + rn[[2, 1]] + rn[[3, 5]],
 rn[[1, 3]] + rn[[2, 1]] + rn[[3, 6]],
 rn[[1, 3]] + rn[[2, 2]] + rn[[3, 1]],
 rn[[1, 3]] + rn[[2, 2]] + rn[[3, 2]],
 rn[[1, 3]] + rn[[2, 2]] + rn[[3, 3]],
 rn[[1, 3]] + rn[[2, 2]] + rn[[3, 4]],
 rn[[1, 3]] + rn[[2, 2]] + rn[[3, 5]],
 rn[[1, 3]] + rn[[2, 2]] + rn[[3, 6]],
 rn[[1, 3]] + rn[[2, 3]] + rn[[3, 1]],
 rn[[1, 3]] + rn[[2, 3]] + rn[[3, 2]],
 rn[[1, 3]] + rn[[2, 3]] + rn[[3, 3]],
 rn[[1, 3]] + rn[[2, 3]] + rn[[3, 4]],
 rn[[1, 3]] + rn[[2, 3]] + rn[[3, 5]],
 rn[[1, 3]] + rn[[2, 3]] + rn[[3, 6]],
 rn[[1, 3]] + rn[[2, 4]] + rn[[3, 1]],
 rn[[1, 3]] + rn[[2, 4]] + rn[[3, 2]],
 rn[[1, 3]] + rn[[2, 4]] + rn[[3, 3]],
 rn[[1, 3]] + rn[[2, 4]] + rn[[3, 4]],
 rn[[1, 3]] + rn[[2, 4]] + rn[[3, 5]],
 rn[[1, 3]] + rn[[2, 4]] + rn[[3, 6]]
 }

gives the answer:

{14, 14, 18, 18, 18.5, 19, 15, 15, 19, 19, 19.5, 20, 15.1, 15.1, \
19.1, 19.1, 19.6, 20.1, 16, 16, 20, 20, 20.5, 21, 14.1, 14.1, 18.1, \
18.1, 18.6, 19.1, 15.1, 15.1, 19.1, 19.1, 19.6, 20.1, 15.2, 15.2, \
19.2, 19.2, 19.7, 20.2, 16.1, 16.1, 20.1, 20.1, 20.6, 21.1, 14.5, \
14.5, 18.5, 18.5, 19., 19.5, 15.5, 15.5, 19.5, 19.5, 20., 20.5, 15.6, \
15.6, 19.6, 19.6, 20.1, 20.6, 16.5, 16.5, 20.5, 20.5, 21., 21.5}

But there must be an easier way to do this using something like Tuples[], Table[], Sum[], Permutations[] so that I can give it a list that has any number of sub-lists, and sub lists that are of any length.

$\endgroup$

3 Answers 3

11
$\begingroup$

Total[Tuples@rn, {2}]

should do.

For cases where a very large number of tuples would be generated,

Fold[Total[Tuples[{##}], {2}] &, rn]

will generally be even quicker, and exhibit considerably lower memory pressure, to the point that it can be an order of magnitude faster because it can avoid paging if RAM gets low. If the ordering of the output is not important, sorting your $rn$ so that smaller lists are first (just a simple rn=Sort@rn) will increase the latter's performance even more.

$\endgroup$
2
  • 3
    $\begingroup$ A slower alternative is Outer[Total[{##}] &, Sequence @@ rn] // Flatten $\endgroup$
    – Bob Hanlon
    Commented Sep 27, 2020 at 19:01
  • $\begingroup$ Your code works quickly: rn = Table[ {1, 2}, {n, 1, 23} ]; { Timing[Total[Tuples@rn, {2}] // Length][[1]], Timing[Fold[Total[Tuples[{##}], {2}] &, rn] // Length][[1]], Timing[Distribute[foo @@ rn, List, foo, List, Plus] // Length][[1]], Timing[Flatten@Outer[Plus, ## & @@ rn] // Length][[1]], Timing[Activate@Tuples[Inactive[Plus] @@ rn] // Length][[1]], Timing[Activate@Tuples[Inactive[Plus] @@ rn] // Length][[1]], Timing[Outer[Plus, Apply[Sequence, rn]] // Length][[1]] } ={0.796875, 0.421875, 14.6094, 13.7656, 18.375, 18.3594, 13.875} $\endgroup$
    – Robjobbob
    Commented Oct 2, 2020 at 1:40
5
$\begingroup$

Few additional alternatives:

Distribute[foo @@ rn, List, foo, List, Plus]

Flatten @ Outer[Plus, ## & @@ rn]

Activate @ Tuples[Inactive[Plus] @@ rn]
$\endgroup$
1
$\begingroup$

I see kglr got here first, but in a different format:

Outer[Plus, Apply[Sequence, rn]] // TableForm

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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