Hello I need some help on how to add a list to a list of list. The program would have to do as below:
{{0,0}, {0}, {0,0,0}}+{1,2,3,4,5,6}
will give
{{1,2}, {3}, {4,5,6}}.
Could this be done? Any help is greatly appreciated. Thanks in advance.
Hello I need some help on how to add a list to a list of list. The program would have to do as below:
{{0,0}, {0}, {0,0,0}}+{1,2,3,4,5,6}
will give
{{1,2}, {3}, {4,5,6}}.
Could this be done? Any help is greatly appreciated. Thanks in advance.
Without testing whether there are as many elements in the first list as there are in the second, the solution is as simple as
listAdd[structured_, flat_] := Module[{i = 1},
Function[elm, elm + flat[[i++]], {Listable}][structured]
]
listAdd[{{a, b}, {c}, {d, e, f}}, {1, 2, 3, 4, 5, 6}]
(* {{1 + a, 2 + b}, {3 + c}, {4 + d, 5 + e, 6 + f}} *)
To understand why this works, please study carefully my answer of this question.
add in the "Like/Long" test I just posted.
– Mr.Wizard
Dec 31 '14 at 23:45
Here is a performance comparison of all methods given in the order of their posting.
Bill's code is not self-contained so I shall use:
bill[a_, b_] :=
Module[{h, list = b},
Map[(h = Take[list, Length[#]]; list = Drop[list, Length[#]]; # + h) &, a]
]
The other functions for ease of execution:
add[a_List, b_List] := a + dynP[b, Length /@ a]
listAdd[structured_, flat_] :=
Module[{i = 1}, Function[elm, elm + flat[[i++]], {Listable}][structured]]
raggedMap = Internal`PartitionRagged[#1[Flatten[#2], #3], Length /@ #2] &;
listAdd1[structured_, flat_] := Module[{cnt = 1, f}, f = Function[x, x + flat[[cnt++]]];
Map[f, structured, {-1}]]
deFlatten[flat_, reference_] :=
Module[{cnt = 1}, Replace[reference, elem_ :> flat[[cnt++]], {-1}]]
listAdd2[structured_, flat_] := deFlatten[Flatten[structured] + flat, structured]
Yi Wang's listAdd3 threw errors so I did not include it in this test.
Generating code for two lists of the like type (Integer) with short sublists:
Needs["GeneralUtilities`"]
a = RandomInteger[9, #] & /@ RandomInteger[{1, 9}, 5000];
b = RandomInteger[9, Length@Flatten@a];
bill[a, b] // AccurateTiming
add[a, b] // AccurateTiming
listAdd[a, b] // AccurateTiming
raggedMap[Plus, a, b] // AccurateTiming
listAdd1[a, b] // AccurateTiming
listAdd2[a, b] // AccurateTiming
Like-types and long sublists:
a = RandomInteger[9, #] & /@ RandomInteger[{1, 500}, 500];
b = RandomInteger[9, Length@Flatten@a];
Unlike types and short sublists:
a = RandomInteger[9, #] & /@ RandomInteger[{1, 9}, 5000];
b = RandomChoice[{"a", "b", "c"}, Length@Flatten@a];
Unlike types and long sublists:
a = RandomInteger[9, #] & /@ RandomInteger[{1, 500}, 500];
b = RandomChoice[{"a", "b", "c"}, Length@Flatten@a];
A table of results:

This question is similar to 7511, which was solved with
dynP[l_, p_] := MapThread[l[[# ;; #2]] &, {{0}~Join~Most@# + 1, #} &@Accumulate@p]
In your case, dynP[{1, 2, 3, 4, 5, 6},{2, 1, 3}], where the second list is the lengths of the desired partitions, gives the answer. If, on the other hand, you wish to work from your template list, use
dynP[[{1, 2, 3, 4, 5, 6}, Length /@ {{0, 0}, {0}, {0, 0, 0}}]
As a function:
add[a_List, b_List] := a + dynP[b, Length /@ a]
Now:
add[{{2, 3}, {5}, {7, 11, 13}}, {1, 2, 3, 4, 5, 6}]
{{3, 5}, {8}, {11, 16, 19}}
Two ways to use Internal`CopyListStructure:
addLsts1 = # + Internal`CopyListStructure[#, #2] &;
addLsts1[{{a, b}, {c}, {d, e, f}}, Range@6]
{{1 + a, 2 + b}, {3 + c}, {4 + d, 5 + e, 6 + f}}
addLsts1 is as fast as Mr.Wizard's add.
A slower alternative:
addLsts2 = Internal`CopyListStructure[#, Flatten[#] + #2] &;
addLsts2[{{a, b}, {c}, {d, e, f}}, Range@6]
{{1 + a, 2 + b}, {3 + c}, {4 + d, 5 + e, 6 + f}}
IF listoflist is only nested one level deep then
listoflist = {{0, 0}, {0}, {0, 0, 0}};
list = {1, 2, 3, 4, 5, 6};
Map[(h = Take[list, Length[#]]; list = Drop[list, Length[#]]; # + h) &, listoflist]
(* {{1, 2}, {3}, {4, 5, 6}} *)
Using TakeList:
alist = {{a, b}, {c}, {d, e, f}};
blist = {1, 2, 3, 4, 5, 6};
alist + TakeList[blist, Length /@ alist]
{{1 + a, 2 + b}, {3 + c}, {4 + d, 5 + e, 6 + f}}
Also:
alist TakeList[blist, Length /@ alist]
{{a, 2 b}, {3 c}, {4 d, 5 e, 6 f}}
raggedMap = Internal`PartitionRagged[#1[Flatten[#2], #3], Length /@ #2] &;
raggedAdd = raggedMap[Plus, #, #2] &;
Usage examples:
raggedAdd {{0, 0}, {0}, {0, 0, 0}}, {1, 2, 3, 4, 5, 6}]
or
raggedMap[Plus, {{0, 0}, {0}, {0, 0, 0}}, {1, 2, 3, 4, 5, 6}]
both give
(* {{1, 2}, {3}, {4, 5, 6}} *)
lst1 = {{a, b}, {c}, {d, e, f}};
lst2 = {1, 2, 3, 4, 5, 6};
raggedAdd[lst1, lst2]
(* {{1+a, 2+b}, {3+c}, {4+d, 5+e, 6+f}} *)
raggedMap[Times, lst1, lst2]
(* {{a, 2 b}, {3 c}, {4 d, 5 e, 6 f}} *)
One solution: map at the last level
listAdd1[structured_, flat_] := Module[{cnt = 1, f},
f = Function[x, x + flat[[cnt++]]];
Map[f, structured, {-1}]]
Another solution: First define a function deFlatten[flat, reference], to undo Flatten, according to a given reference list:
deFlatten[flat_, reference_] := Module[{cnt = 1},
Replace[reference, elem_ :> flat[[cnt++]], {-1}]]
For example,
deFlatten[{a, b, c}, {1, {2, 3}}]
{a, {b, c}}
Then it is trivial to implement listAdd:
listAdd2[structured_, flat_] :=
deFlatten[Flatten[structured] + flat, structured ]
A third solution, by keeping the position of the list in MapIndexed, and restore the position using ReplacePart
listAdd3[structured_, flat_] := Module[{f}, ReplacePart[structured,
Flatten @ MapIndexed[f, structured, {-1}] + flat /. n_ + f[m_, pos_] :> (pos :> m + n)]]