# 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. Commented Nov 23, 2013 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. Commented Nov 23, 2013 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]]). Commented Nov 23, 2013 at 15:18
• Looks like this would almost work, but for Append behaving differently. Commented Nov 23, 2013 at 15:31
• Instead use Join Commented Nov 23, 2013 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. ) Commented Nov 23, 2013 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];] Commented Nov 23, 2013 at 13:21

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

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