开发者

Appending to the rows of a table

I have a two dimensional list and a one dimensional list. I would like to insert the 1D list into the 2D list as an additional column. For example:

array = {{a,1,2},{b,2,3},{c,3,4}};
column = {x,y,z};

becomes

final = {{a,1,2,x},{b,2,3,y},{c,3,4,z}};

I have done this inelegantly:

Table[Insert[array[[i]], column[[i]], 4], {i, Len开发者_开发技巧gth[array]}];

My question: what is the proper way to do this in Mathematica? I don't think it needs the loop I'm using. My solution feels ugly.


For example:

 Transpose@Append[Transpose@array, column]

You can also make is a function like so:

 subListAppend = Transpose@Append[Transpose@#1, #2] &;
 subListAppend[array, column]

which makes it easier if you have to use it frequently. And of course if you want to insert at any place other than just the end you can use Insert[].

subListInsert = Transpose@Insert[Transpose@#1, #2, #3] &;
subListInsert[array, column, 2]
--> {{a, x, 1, 2}, {b, y, 2, 3}, {c, z, 3, 4}}

EDIT: Since the obligatory speed optimization discussion has started, here are some results using this and a 10000x200 array:

ArrayFlatten@{{array, List /@ column}}:             0.020 s
Transpose@Append[Transpose@array, column]:          0.067 s
MapThread[Append, {array, column}]:                 0.083 s  
MapThread[Insert[#1, #2, 4] &, {array, column}]:    0.095 s
Map[Flatten, Flatten[{array, column}, {2}]]:        0.26 s
ConstantArray based solution:                       0.29 s
Partition[Flatten@Transpose[{array, column}], 4]:   0.48 s

And the winner is ArrayFlatten!


Another possibility is

result = ConstantArray[0, Dimensions[array] + {0, 1}];
result[[All, 1 ;; Last[Dimensions[array]]]] = array;
result[[All, -1]] = column;

which seems to be faster on my computer for large numeric matrices, although it requires an additional variable. If you're dealing with real-valued entries you'll want to use

result = ConstantArray[0.0, Dimensions[array] + {0, 1}];

to keep the speed gains.

There's also

MapThread[Append, {array, column}]

which is also fast (and elegant IMO) but will unpack the result. (But if you have symbolic entries as in the example, that's not a concern.)


Here is my try using Join

In[11]:= Join[array,List/@column,2]
Out[11]= {{a,1,2,x},{b,2,3,y},{c,3,4,z}}

It might be comparable to the fastest one among previously mentioned programs.


How about this?

pos = 4;
MapThread[Insert[#1, #2, pos] &, {array, column}]


I (sometimes) like to transpose with Flatten, as it works with a 'ragged' array.

Map[Flatten, Flatten[{array, column}, {2}]]

giving

{{a, 1, 2, x}, {b, 2, 3, y}, {c, 3, 4, z}}

But if, say, the column has only 2 elements

column2 = {x, y};
Map[Flatten, Flatten[{array, column2}, {2}]]

giving

{{a, 1, 2, x}, {b, 2, 3, y}, {c, 3, 4}}

(Transpose will not work here)


Still:

k= Partition[Flatten@Transpose[{#, {x, y, z}}], 4]&

k@ {{a, 1, 2}, {b, 2, 3}, {c, 3, 4}}

(*
-> {{a, 1, 2, x}, {b, 2, 3, y}, {c, 3, 4, z}}
*)


Though not as practical or efficient as some of the extant methods, here are two more to add to the list:

ArrayPad[array, {0,{0,1}}, List /@ column]

PadRight[array, Dimensions[array] + {0, 1}, List /@ column]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜