# Adding elements to some sublists of unequal length

Complicated title for a simple problem: I have list

a = {{1, 3, 5, 2}, {2, 6, 2}, {3, 5, 6, 1, 2}, {4, 2}}


In which the first element of each sublist is basically an index. The following values are the actual data. Then I want to add data to this list, e.g.,:

b = {{2, 1}, {4, 3}}


Which means that to the list with the index '2' the '1' should be added and the list with the index '4' the '3' should be added, so the result reads:

{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}


I found a couple of rather complicated, i.e., time consuming solutions involving loops. However, the actual datset is huge and is part of a numerical simulation, i.e., this procedure needs to be very fast.

Fold[Insert[#1, Last[#2], {First[#2], -1}] &, a, b]


Perhaps something like this:

ReplacePart[a, #1 -> Append[a[[#1]], #2]& @@@ b]


If data are large and speedup is needed you might want to try Join

ReplacePart[a, #1 -> Join[a[[#1]], {#2}] & @@@ b]


In case you want value of a to be the new list with added elements, you whether can use AppendTo:

ReplacePart[a, #1 -> AppendTo[a[[#1]], #2] & @@@ b]


or simply reassign:

a = ReplacePart[a, #1 -> Append[a[[#1]], #2] & @@@ b]


You can make b into a list of rules

rules = {#, a__} :> {#, a, #2} & @@@ b;


and use it with ReplaceAll:

a /. rules


{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}

or with Replace:

Replace[a, rules, All]


{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}

This approach works for any ordering of the elements in the input list:

c = RandomSample[a]


{{2, 6, 2}, {3, 5, 6, 1, 2}, {1, 3, 5, 2}, {4, 2}}

c /. rules


{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}

Replace[c, rules, All]


{{2, 6, 2, 1}, {3, 5, 6, 1, 2}, {1, 3, 5, 2}, {4, 2, 3}}

From the Association universe:

KeyValueMap[Flatten @* List] @ Merge[# &] @ Map[GroupBy[First -> Rest], {a, b}]


{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}

Or

KeyValueMap[Flatten @* List] @ Merge[# &] @ MapApply[#1 -> {##2} &, Join[a, b]]


{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}

Clear["Global*"];
a = {{1, 3, 5, 2}, {2, 6, 2}, {3, 5, 6, 1, 2}, {4, 2}};
b = {{2, 1}, {4, 3}};

c = Join[b, Array[{#, x} &, Length@a]] // DeleteDuplicatesBy[First] //
SortBy[First]


{{1, x}, {2, 1}, {3, x}, {4, 3}}

Using Join:

Join the second column of c with a and delete the x:

Join[a, List /@ c[[All, 2]], 2] /. x -> Nothing


{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}

Another method using GroupBy:

Values[GroupBy[Catenate[{a, b}], First, If[Length[#] == 2,
Sequence @@@ {#[[1, All]], #[[2]][[2;;]]}, #[[1]]] &]]

(*{{1, 3, 5, 2}, {2, 6, 2, 1}, {3, 5, 6, 1, 2}, {4, 2, 3}}*)
`