How to insert / merge a list into another list?

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.

• I made an error, but have edited it, sorry. – nilo de roock Nov 23 '13 at 12:21
• If you really want fast inserts, you should not use lists. The choice of the appropriate data structure to use would depend on other things you want to do with this collection of points. Quadtree comes to mind. – Leonid Shifrin Nov 23 '13 at 13:32
• The trivial scheme way to do it would compose append with take and drop (e.g. Append[Take[xs, n], vs, Drop[xs, n]]). – wdkrnls Nov 23 '13 at 15:18
• Looks like this would almost work, but for Append behaving differently. – wdkrnls Nov 23 '13 at 15:31
• Instead use Join – wdkrnls Nov 23 '13 at 15:34

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}}

• I did not know about the function FlattenAt, I like the third option. ( Imagine I hadn't asked the question. ) – nilo de roock Nov 23 '13 at 12:24

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}}

• 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
☺ = (♯ = #; ♯[[#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}}