8

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?

7 Answers7

5

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]], ##} &)]
WReach
  • 68,832
  • 4
  • 164
  • 269
4

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
]
Sjoerd Smit
  • 23,370
  • 46
  • 75
3

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}]
lericr
  • 27,668
  • 1
  • 18
  • 64
3
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}]
Syed
  • 52,495
  • 4
  • 30
  • 85
3

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}}}*)
E. Chan-López
  • 23,117
  • 3
  • 21
  • 44
3
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

user1066
  • 17,923
  • 3
  • 31
  • 49
2

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]
lericr
  • 27,668
  • 1
  • 18
  • 64