# Convert list of lists to cumulative join

I have this:

list[1]={1,2,3};
list[2]={7,8,9};
list[3]={15,20,22};


I want this:

cumulativeList[1]={1,2,3};
cumulativeList[2]={1,2,3,7,8,9};
cumulativeList[3]={1,2,3,7,8,9,15,20,22};


Sort of like Accumulate, but using Join instead of Sum. I think it might be possible using FoldList but I'm getting confused.

• Well, then why don't you try to use FoldList with Join for this? It will work! :) Commented Jul 1, 2013 at 10:28
• You shouldn't use capital letters in the beginning of variable names, if that's what List is. It will cause collisions, as in this case. Commented Jul 1, 2013 at 10:32
• Toph, your idea is absolutely right. You need Accumulate with Join instead of Sum. And you can use FoldList. So have a look at the documentation for Accumulate, it says: Accumulate[list] is effectively equivalent to Rest[FoldList[Plus,0,list]]. So there you go! Try Rest[FoldList[Join,{},list]]. Commented Jul 1, 2013 at 11:40
• Ok, let me rewrite that question: are you aware of the fact that you are not constructing a List by doing list[1]=... but merely assigning values to a symbol? [] associates values to symbols. In contrast, [[]] refers to list indices. In the title you wrote that you have a list of lists, and that would be list={{1,2,3}..} as mentioned in the comment above. Since the answers so far do not deal with list actually being a List, this is a question to think about first. Commented Jul 1, 2013 at 12:47
• Wow just checked back and I'm floored and delighted with the amount of activity here. Theo and Andre, you're correct that I hadn't understood that. Y'all are great, I have to go but I'll look over all of this, thanks for the help, I'll be back.
– Toph
Commented Jul 2, 2013 at 9:24

## 11 Answers

Rather than using FoldList, this seems to be a perfect application of recursion and memoization, which leads to a very elegant solution:

(* Your original list *)
list[1] = {1, 2, 3};
list[2] = {7, 8, 9};
list[3] = {15, 20, 22};

(* The cumulative list *)
cumulativeList[0] = {};
cumulativeList[n_] := cumulativeList[n] = cumulativeList[n - 1] ~Join~ list[n]


Now you just need to evaluate cumulativeList[3] and automatically, all the other values (i.e. 1, 2) are calculated.

cumulativeList[3]
(* {1, 2, 3, 7, 8, 9, 15, 20, 22} *)

Table[cumulativeList[n], {n, 3}]
(* {{1, 2, 3}, {1, 2, 3, 7, 8, 9}, {1, 2, 3, 7, 8, 9, 15, 20, 22}} *)

• hmm, although I like the concept of memoization, I think this is not a good example of it. FoldList is specifically made for this purpose and it will not re-evaluate. Also, intuitively, I would not do this with recursive code, but this might be something personal, as I tend to use recursive programming in Mathematica only on very rare occasions (same for iterative programming). Moreover, I believe memoization would require variable localization and it produces memory overhead, so in summary I don't feel this is as clean a code as with FoldList. Commented Jul 1, 2013 at 12:06
• @TheoTiger What do you mean this will "re-evaluate"? The explicit purpose of memoization is to compute once and store the result, so as to avoid re-evaluation, so I'm not sure why you think this does. Also, what do you mean "variable localization" and "memory overhead"? This is the exact structure that the OP specifically asked for in the question, with the addition of down-values for 0 and n_ (which can be removed after computing, if it bothers you).
– rm -rf
Commented Jul 1, 2013 at 12:15
• FoldList will also avoid re-evaluation of previous terms, as does memoization. Yep, you either need to clean up after computation or use something like Module[{comulativeList},...] in order to re-use this function for a different list and to release memory consumed by the down-values. However, I somehow feel this is too complicated for this rather straight-forward problem, what do you think? Commented Jul 1, 2013 at 12:27
• You are right, your version exactly matches the structures being asked for. However, rather than fulfilling that specific structure, I would take a wild guess and say to the questioner that list and cumulativeList being regular Lists is more likely to be what he wants. This is why I interpreted his question like that in first place, but I will ask him. Commented Jul 1, 2013 at 12:29
• This is nice, +1. For very large list of lists, you may want to memoize the partial linked lists instead, and then Flatten them and use a single Join when the function is later called for a particular n. This would make the initial call very fast (linear in the number of lists), for the price of some (not very significant) added overhead for the subsequent calls for specific n. As of now, your initial call is O(m^2), where m is the total number of elements in all lists. Commented Jul 1, 2013 at 19:07
list[1] = {1, 2, 3};
list[2] = {7, 8, 9};
list[3] = {15, 20, 22};

With[{x = Array[cumulativelist, 3]},
x = Rest@FoldList[Join, {}, Array[list, 3]]]


{{1, 2, 3}, {1, 2, 3, 7, 8, 9}, {1, 2, 3, 7, 8, 9, 15, 20, 22}}

cumulativelist[3]


{1, 2, 3, 7, 8, 9, 15, 20, 22}

Here is a solution :

list[1] = {1, 2, 3};
list[2] = {7, 8, 9};
list[3] = {15, 20, 22};

Fold[Join[#1, #2] &, {}, {list[1]}]
Fold[Join[#1, #2] &, {}, {list[1], list[2]}]
Fold[Join[#1, #2] &, {}, {list[1], list[2], list[3]}]


{1, 2, 3}
{1, 2, 3, 7, 8, 9}
{1, 2, 3, 7, 8, 9, 15, 20, 22}

Note that the variable list begins with a lowercase. Using a uppercase is not recommended. It enters in conflict with Mathematica symbol names.

• You could just use Join instead of Join[#1, #2] &. And using FoldList as in Rest[FoldList[Join, {}, {list[1], list[2], list[3]}]] might simplify things further Commented Jul 1, 2013 at 10:46
• OK thanks! I ended up doing this: Do[cumulativeList[i] = Flatten[Drop[list, {i + 1, 20}]],{i, 20}]; i.e. flattening progressively less-truncated subsets of the original list of lists. Worked for me & appears to have the advantage of scaling to any number of lists (here 20) without making you type list[1],list[2],list[3]... does that make sense?
– Toph
Commented Jul 1, 2013 at 11:03
• It would have sense only if list = {{1,2,3},{7,8,9},{15,20,22}}, which is not the case with the definitions : list[1]={1,2,3};list[2]= ... . I can't understand that you say "Worked for me". If you want to see what is really list, type ?list then shift-return. Commented Jul 1, 2013 at 14:19

Table offers a simple approach without recursion and memoization.

concatenate[f_, {n_, m_}] := Join @@ Table[f[k], {k, n, m}]


Example

concatenate[list, {1, 3}]


{1, 2, 3, 7, 8, 9, 15, 20, 22}

Perhaps even simpler is to use Map

list[1] = {1, 2, 3};
list[2] = {7, 8, 9};
list[3] = {15, 20, 22};
Flatten[list[#] & /@ Range[3]]

{1, 2, 3, 7, 8, 9, 15, 20, 22}


You can make this into a function easily

cumList[list_] := Flatten[list[#] & /@ Range[Length[DownValues[list]]]]


Calling cumList[list] then gives the same answer as above. (Thanks to Anon for noticing the extra Join).

• I believe Join is superfluous: Flatten[list[#] & /@ Range[Length[DownValues[list]]]] Commented Jul 1, 2013 at 13:09

Perhaps the shortest solution is this:

Flatten@DownValues[list][[All, 2]]


{1, 2, 3, 7, 8, 9, 15, 20, 22}

And the requested function cumulativeList:

cumulativeList[n_] := Flatten@DownValues[list][[1 ;; n, 2]]


In case you chose to write your list like this instead, it would be simpler:

list = {{1, 2, 3}, {7, 8, 9}, {15, 20, 22}}


Namely,

cumulativeList[n_] := Flatten[list[[1 ;; n]]]


Here is an iterative example:

(* Your lists *)
Clear[cumulativeList]
cumulativeList[n_] := Module[{},
cumulativeList[0] = {};
For[x = 0, x < n, x++,
Print[cumulativeList[x + 1] =
Join[cumulativeList[x], list[x + 1]]]]]

cumulativeList[1]

(*{1, 2, 3}*)
cumulativeList[2]

(*{1, 2, 3, 7, 8, 9}*)
cumulativeList[3]

(*{1, 2, 3, 7, 8, 9, 15, 20, 22}*)

FoldList[(cumulativeList[#2[[1, 1, 1]]] = Join[#1, #2[[2]]]) &, {},
DownValues[list]]


This gives you all the indexed variables at once (which is what you asked), rather than providing a function to calculate them. Works for all available indices, even with gaps in numbering and even for non-numeric indices.

Here's a one-liner using Join and a pure function:

list[1] = {1, 2, 3};
list[2] = {7, 8, 9};
list[3] = {15, 20, 22};

JoinList[number_] := Join @@ (list[#] & /@ Range[number]);


Then you can evaluate

JoinList[1]


{1, 2, 3}

JoinList[2]


{1, 2, 3, 7, 8, 9}

JoinList[3]


{1, 2, 3, 7, 8, 9, 15, 20, 22}

Hope this helps!

• This isn't fundamentally different from bill s' or David's answer.
– rm -rf
Commented Jul 1, 2013 at 21:48
• @rm-rf Yup, looks almost exactly the same, I only realized it after I posted.. Commented Jul 1, 2013 at 21:51
Flatten[list /@ #] & /@ Range[Range[3]]


{{1, 2, 3}, {1, 2, 3, 7, 8, 9}, {1, 2, 3, 7, 8, 9, 15, 20, 22}}

• Slightly shorter: Join @@ Array[list, #] & ~Array~ 3 or Array[list, #, 1, Join] & ~Array~ 3 Commented Jul 30, 2017 at 5:51

Terse syntax for FoldList:

FoldList[Join, Array[list, 3]]

{{1, 2, 3}, {1, 2, 3, 7, 8, 9}, {1, 2, 3, 7, 8, 9, 15, 20, 22}}


Reference: