Combining lists of lists with random structure

I have two lists which I would like to combine. One is of a random structure, which might be:

l1={{3, 2, 4, 2}, {2, 3}, {4, 3}, {{2, 2}}, {{3, 3}}, {3, 2}}


where the elements in each sublist may themselves be numbers, or lists.

From this, I create a list given by:

l2=Join[{0}, Accumulate[Flatten[l1, 1]]]


which gives in this case:

{0, 3, 5, 9, 11, 13, 16, 20, 23, {25, 25}, {28, 28}, {31, 31}, {33, 33}}


I now want to go through the original list, and append to each entry in that list, an entry from the second, in order, to end up with:

{{{3, 0}, {2, 3}, {4, 5}, {2, 9}}, {{2, 11}, {3, 13}}, {{4, 16}, {3, 20}}, {{{2, 2}, 23}}, {{{3, 3}, {25, 25}}}, {{3, {28, 28}}, {2, {31, 31}}}}


I can do this using a loop, but I would like to find a functional way to write it. I have tried using various map, list and thread commands, but so far have been unable to solve it.

• Related: (3585) Jan 12, 2017 at 13:30

Module[{i = 1},
Map[{#, l2[[i++]]} &, l1, {2}]
]


If you don't need l2 separately you can eliminate the use of Accumulate entirely with:

Module[{t = 0},
Map[{#, # &[t, t += #]} &, l1, {2}]
]


The inner function # &[t, t += #] is just a way to AddTo t but return the old value of t. Equivalently: First[{t, t += #}].

• Beautiful, thank you! Jan 12, 2017 at 13:22
• @Jonathan You're welcome, and I am glad I could help. As always however I recommend waiting 24 hours before Accepting an answer to encourage everyone who has an answer to post it. Jan 12, 2017 at 13:24
• @Jonathan Please see my update. Jan 12, 2017 at 13:53
• thanks for the tip. regarding accepting the answer. I shall keep this in mind in the future. Indeed I don't need the intermediate step, so the update is very useful too. Jan 12, 2017 at 15:44

Also,

l3 = InternalPartitionRagged[Most@l2, Length /@ l1];
Transpose /@ Transpose[{l1, l3}]


{{{3, 0}, {2, 3}, {4, 5}, {2, 9}},
{{2, 11}, {3, 13}},
{{4, 16}, {3, 20}},
{{{2, 2}, 23}},
{{{3, 3}, {25, 25}}},
{{3, {28, 28}}, {2, {31, 31}}}}

Using TakeList:

l1 = {{3, 2, 4, 2}, {2, 3}, {4, 3}, {{2, 2}}, {{3, 3}}, {3, 2}};
l2 = Join[{0}, Accumulate[Flatten[l1, 1]]];

Thread[{l1, TakeList[l2, Length /@ l1]}] // Map[Transpose]


{{{3, 0}, {2, 3}, {4, 5}, {2, 9}}, {{2, 11}, {3, 13}}, {{4, 16}, {3,
20}}, {{{2, 2}, 23}}, {{{3, 3}, {25, 25}}}, {{3, {28, 28}}, {2, {31, 31}}}}

Using MapThread and FoldPairList, an equivalent form to the one proposed by @Syed is the following:

l1 = {{3, 2, 4, 2}, {2, 3}, {4, 3}, {{2, 2}}, {{3, 3}}, {3, 2}};
l2 = Join[{0}, Accumulate[Flatten[l1, 1]]];
l3 = Length /@ l1;

MapThread[Transpose@List[#1, #2] &, {l1, FoldPairList[TakeDrop, l2, l3]}]


{ {{3, 0}, {2, 3}, {4, 5}, {2, 9}}, {{2, 11}, {3, 13}}, {{4, 16}, {3, 20}}, {{{2, 2}, 23}},
{{{3, 3}, {25, 25}}, {{3, {28, 28}}, {2, {31, 31}}}} }

• The FoldPairList technique is in the docs as an equivalent to TakeList. I still struggle with the use of FoldPairList` though.
– Syed
Apr 6, 2023 at 3:21
• The same thing happens to me, that's why I always pay attention to the posts where there's manipulation of lists. Apr 6, 2023 at 20:40