8
$\begingroup$

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.

$\endgroup$

6 Answers 6

9
$\begingroup$
Fold[Insert[#1, Last[#2], {First[#2], -1}] &, a, b]
$\endgroup$
5
$\begingroup$

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]
$\endgroup$
5
$\begingroup$

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

$\endgroup$
1
$\begingroup$

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

$\endgroup$
1
$\begingroup$
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}}

$\endgroup$
0
$\begingroup$

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}}*)
$\endgroup$

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.