11

Background: I am working on a 2D geometry algorithm where I need to insert a list of 2D points into another list of 2D points. Somewhat to my surprise I found no Mathematica function capable of doing this. My requirement is for a function that when provided for example:

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

and

 {{100,100}, {200,200}}

returns

{{1,1},{2,2}, {100,100}, {200,200},{3,3},{4,4},{5,5}} 

I looked at various Mathematica functions where Insert seemed the candidate to use, now

 Insert[{{1,1},{2,2},{3,3},{4,4},{5,5}},{{100,100}, {200,200}},3] 

returns

 {{1, 1}, {2, 2}, {{100, 100}, {200, 200}}, {3, 3}, {4, 4}, {5, 5}}

note the extra braces around

 {100, 100}, {200, 200}

Inspired by this question/answers I created insertM.

 insertM[list_, values_, at_] := Module[{i = 0},
   Insert[list, "mark", Array[{at} &, Length[values]]] /. "mark" :> (++i; values[[i]])]

which gives

 insertM[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}, {{100, 100}, {200, 200}}, 3]
 {{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

Although insertM does the job, I have this ' there must be a better way ' feeling.

Now my question(s): Is there a Mathematica function that performs my requirement? If not, is there a better function then insertM to do this? In better I rank beautiful code (short, functional) highest unless it is significantly slower than a less beautiful alternative.

nilo de roock
  • 9,657
  • 3
  • 35
  • 77

4 Answers4

13

A few options:

insertSequence1[x_, y_, n_] := Insert[x, Unevaluated[Sequence @@ y], n]

insertSequence2[x_, y_, n_] := Fold[Insert[##, n] &, x, Reverse@y]

insertSequence3[x_, y_, n_] := Insert[x, y, n] ~FlattenAt~ n

x = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
y = {{100, 100}, {200, 200}};

insertSequence1[x, y, 3]
insertSequence2[x, y, 3]
insertSequence3[x, y, 3]

{{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

{{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

{{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

Simon Woods
  • 84,945
  • 8
  • 175
  • 324
7

Just for variety:

l1 = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
l2 = {{100, 100}, {200, 200}};

Just using Join:

f[x_, y_, n_] := Join[x[[1 ;; n - 1]], y, x[[n ;; -1]]]

So,

f[l1, l2, 3]

yields:

{{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

ubpdqn
  • 60,617
  • 3
  • 59
  • 148
  • It is much faster than my previous ( but more beautiful ) choice: insertSeqA[x_, y_, n_] := FlattenAt[Insert[x, y, n], n]; insertSeqB[x_, y_, n_] := Join[x[[1 ;; n - 1]], y, x[[n ;; -1]]] Timing[insertSeqA[Flatten[Array[{#1, #2} &, {1000, 1000}], 1], Flatten[Array[{#1, #2} &, {100, 100}], 1], 1000];] Timing[insertSeqB[Flatten[Array[{#1, #2} &, {1000, 1000}], 1], Flatten[Array[{#1, #2} &, {100, 100}], 1], 1000];] – nilo de roock Nov 23 '13 at 13:21
3

Since V 13.1 there is Splice which simplifies @Simon Wood's insertSequence3 to

dt = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
in = {{100, 100}, {200, 200}};

Insert[dt, Splice[in], 3]

{{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

eldo
  • 67,911
  • 5
  • 60
  • 168
1
☺ = (♯ = #; ♯[[#2]] = ## &[#[[#2]], ## & @@ #3]; ♯) &;

☺[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}, 2, {{100, 100}, {200, 200}}]

{{1, 1}, {2, 2}, {100, 100}, {200, 200}, {3, 3}, {4, 4}, {5, 5}}

kglr
  • 394,356
  • 18
  • 477
  • 896