8

This is strongly related to the following Questions:

I am looking for an efficient method to insert an array into an array. Let’s assume that both arrays have similar number of rows. Let’s further assume insertion is by column.

a = {{a1, b1, c1, d1, e1}, {a2, b2, c2, d2, e2}, {a3, b3, c3, d3, e3}}; (*example may be larger*)
b = {{x1, y1, z1}, {x2, y2, z2}, {x3, y3, z3}}; (*example may be larger*)

Q1: What is the fastest method to insert b into a at a position p. Let’s assume that both arrays have similar number of rows. Let’s further assume insertion is by column.

My current method is as follows:

insertarray[a_, b_, pos_] :=
FlattenAt[
Transpose@Insert[Transpose@a, b[[##]], pos ] & [Range[Length@a]], 
Table[{i, pos}, {i, 1, Length@a}]];

which allows me to do

insert array

Q2: Some times I have to intersperse columns of b into a at multiple positions. How do I best extend insertarray so that:

insertarray[a,b,{1,2,5}]//MatrixForm

enter image description here

Pam
  • 1,867
  • 11
  • 24
  • 1
    "Insertion" is not very well defined as shown unless a and b both have the same length. If this is the case, you should tell everyone that constraint. – VF1 Mar 21 '14 at 15:14
  • @VF1 a and b both have the same number of column elements... but yes, it would be better to be explicit whether the insertion is by row or column (esp. with square matrices) – rm -rf Mar 21 '14 at 15:16
  • Edited for clarity. Added constraint insertion is by column. – Pam Mar 21 '14 at 15:17

4 Answers4

10

Q1

Join[a[[;; , ;; 1]], b, a[[;; , 2 ;;]], 2]

enter image description here

One may want to create function

insCol[a_, b_, n_] := Join[a[[;; , ;; n - 1]], b, a[[;; , n ;;]], 2]

insRow[a_, b_, n_] := Join[a[[;; n - 1]], b, a[[n ;;]]]

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • This one's really fast (and the cleanest solution, too) - good job! – VF1 Mar 21 '14 at 17:01
  • @VF1 Great you like it, thanks ;) – Kuba Mar 21 '14 at 17:36
  • I really like this solution. its very clean and does the job well… – Pam Mar 21 '14 at 17:59
  • @Kuba , how can this function be used to add the array/ matrix b after EACH array of the original matrix a? – Titus Jul 25 '19 at 06:55
  • @Titus do you mean after each column of a? – Kuba Jul 25 '19 at 07:28
  • @Kuba almost. I am looking for a way to input rows of 0 in a matrix, such as in the following example ted = Table[Range[3], {3}]; stan2 = ConstantArray[{{0, 0, 0}, {0, 0, 0}}, 3]; Partition[Flatten[Thread[{stan2, ted}]], 3] Having the example for columns as well would help – Titus Jul 25 '19 at 07:34
2

After a few attempts, the following gives a noticeable if unremarkable improvement over insertarray:

columnInsert[a_, b_, pos_] := 
  MapThread[Join[#1[[;; pos - 1]], #2, #1[[pos ;;]]] &, {a, b}];

Your second functionality doensn't actually need anything fancy, just some swaps afterwards:

SetAttributes[columnInsert`swap, HoldFirst];
columnInsert`swap[mat_, first_, list_] :=
 Module[{i = first}, 
  Scan[columnInsert`tmp = mat[[All, i]]; 
     mat[[All, i++]] = mat[[All, #]]; 
     mat[[All, #]] = columnInsert`tmp; &, list]; mat]
columnInsert[a_, b_, pos_List] := 
 Module[{res = columnInsert[a, b, First@pos]},
  columnInsert`swap[res, First@pos, pos]; res]
VF1
  • 4,702
  • 23
  • 31
  • VF1. Thanks. I tried the MapThread method as well… I was almost going to accept this as the solution… – Pam Mar 21 '14 at 18:01
0

I haven't had a chance to test if this is faster (probably not), but I find it easier to read:

Block[{x, T = Transpose}, Insert[T@a, x, 2] /. x -> Sequence @@ T@b // T]

or alternately:

MapThread[Flatten[## ~Insert~ 2] &, {a, b}]

Both give the following:

rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • You beat me to the second one. I didn't find it much faster, though. One thing that sped it up slightly is Flatten[..., 1] – VF1 Mar 21 '14 at 15:34
0

Inserting b at column p :-

a = {{a1, b1, c1, d1, e1}, {a2, b2, c2, d2, e2}, {a3, b3, c3, d3, e3}};
b = {{x1, y1, z1}, {x2, y2, z2}, {x3, y3, z3}};

p = 4;

c = ReleaseHold@MapThread[Insert, {a, Hold[Sequence @@ #] & /@ b, Table[p, {Length@a}]}];

MatrixForm[c]

enter image description here

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108
  • I tried something along these lines, but I found the additional ReleaseHold was too expensive - the whole expression needed to be traversed again for Holds. – VF1 Mar 21 '14 at 17:00
  • @VF1 - I wondered. It will be interesting to see the timings. – Chris Degnen Mar 21 '14 at 18:39