10
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ Related: (3585) $\endgroup$
    – Mr.Wizard
    Jan 12, 2017 at 13:30

4 Answers 4

8
$\begingroup$

This matches your output:

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 += #}].

$\endgroup$
4
  • $\begingroup$ Beautiful, thank you! $\endgroup$ Jan 12, 2017 at 13:22
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Jan 12, 2017 at 13:24
  • $\begingroup$ @Jonathan Please see my update. $\endgroup$
    – Mr.Wizard
    Jan 12, 2017 at 13:53
  • $\begingroup$ 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. $\endgroup$ Jan 12, 2017 at 15:44
6
$\begingroup$

Also,

l3 = Internal`PartitionRagged[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}}}}

$\endgroup$
2
$\begingroup$

enter image description here

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}}}}

$\endgroup$
0
2
$\begingroup$

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}}}} }

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

Your Answer

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

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