6
$\begingroup$

I have two lists. One with three levels (list) and a second one (list 2)

list = {{{2, 0}, {2, 3}}, 
        {{5, 3}, {4, 0}},
        {{0, 5}, {0, 0}}}
list2 = {1,2,3}

and I want to combine the pairs of each second level from list with list2 to get

listcombined = {{{1, 2, 0}, {1, 2, 3}}, 
                {{2, 5, 3}, {2, 4, 0}},
                {{3, 0, 5}, {3, 0, 0}}}

Right now I used Map Indexedwith the following function and got

combine [x_,index_]:={list2[[[index[1]]]],x}
MapIndexed [combine,list,{2}]

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

To get the desired list I then use first Flatten and two times Partition. Is there also an easier way, which avoids the last three steps?

$\endgroup$

7 Answers 7

4
$\begingroup$

Here is a direct way using MapIndexed:

MapIndexed[Prepend[#, list2[[#2[[1]]]]] &, list, {2}]

and another way using ReplacePart:

ReplacePart[list, {i_, _, 0} :> ({list2[[i]], ##} &)]
$\endgroup$
3
$\begingroup$

If you reshape list2 to have the same depth as list, you can Join them directly at the deepest level:

Join[
 Map[List, Transpose @ ConstantArray[list2, {2}], {2}],
 list,
 3
]
$\endgroup$
2
$\begingroup$

I might start with MapThread. Let's see what we get with a dummy function:

MapThread[f, {list, list2}]
(* {f[{{2, 0}, {2, 3}}, 1], f[{{5, 3}, {4, 0}}, 2], f[{{0, 5}, {0, 0}}, 3]} *)

So, we've reduced the problem to defining f in a way that prepends its second argument to every member of its first argument. We could do something like this:

PrependToEach[list_, elem_] := Prepend[elem] /@ list

Combine these into:

MapThread[PrependToEach, {list, list2}]
$\endgroup$
2
$\begingroup$

There are also some nifty padding functions, the best one for this case might be ArrayPad. To use it, we need to manipulate list2 into the right form:

ArrayPad[list, {{0, 0}, {0, 0}, {1, 0}}, List@*List /@ list2]
$\endgroup$
2
$\begingroup$

Just for fun, the following puzzle in the form of code works:

ArrayReshape[Map[Flatten@Append[#[[1]], #[[2]]] &, Level[Map[Thread, Thread[Map[Composition[Transpose, List, ConstantArray[#, Mean[Map[Length, list, {1}]]] &], list2] -> list]], {Mean[Map[Length, list, {1}]]}]], MapAt[# + 1 &, Dimensions[list], Last[list2]]]

The result:

enter image description here

Or more simple using Table:

Table[Prepend[list[[i, j]], list2[[i]]], {i, 1, Length[list2]}, {j, 1,Mean[Map[Length, list, {1}]]}]
(*{{{1, 2, 0}, {1, 2, 3}}, {{2, 5, 3}, {2, 4, 0}}, {{3, 0, 5}, {3, 0, 0}}}*)
$\endgroup$
2
$\begingroup$
Clear[list1, list2];

list1 = {{{2, 0}, {2, 3}}, {{5, 3}, {4, 0}}, {{0, 5}, {0, 0}}};
list2 = {1, 2, 3};

Transpose[{List /@ list2, list1}]

> {{{1}, {{2, 0}, {2, 3}}}, {{2}, {{5, 3}, {4, 0}}}, {{3}, {{0, 5}, {0, 
>     0}}}}

Now use Thread:

res = Thread[Join[First@#, Transpose@Last@#]] & /@ 
  Transpose[{List /@ list2, list1}]

MatrixForm /@ {list2, list1, res}

listcombined == res (*True*)

enter image description here


Another solution using Table:

res2 = Table[
  Prepend[#, list2[[i]]] & /@ list1[[i]], {i, 1, Length@list1}]
$\endgroup$
2
$\begingroup$
ArrayFlatten[{#}] & /@ Thread[{list2, list}]



(* {{{1, 2, 0}, {1, 2, 3}}, {{2, 5, 3}, {2, 4, 0}}, {{3, 0, 5}, {3, 0, 0}}} *)


% ==listcombined

True

Edit

Because this method is almost identical to a previous answer of mine, I've marked it 'community wiki'. Feel free to edit

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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