11
$\begingroup$

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.

$\endgroup$
5
  • $\begingroup$ I made an error, but have edited it, sorry. $\endgroup$ Commented Nov 23, 2013 at 12:21
  • 3
    $\begingroup$ 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. $\endgroup$ Commented Nov 23, 2013 at 13:32
  • $\begingroup$ The trivial scheme way to do it would compose append with take and drop (e.g. Append[Take[xs, n], vs, Drop[xs, n]]). $\endgroup$
    – wdkrnls
    Commented Nov 23, 2013 at 15:18
  • $\begingroup$ Looks like this would almost work, but for Append behaving differently. $\endgroup$
    – wdkrnls
    Commented Nov 23, 2013 at 15:31
  • $\begingroup$ Instead use Join $\endgroup$
    – wdkrnls
    Commented Nov 23, 2013 at 15:34

4 Answers 4

13
$\begingroup$

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

$\endgroup$
1
  • $\begingroup$ I did not know about the function FlattenAt, I like the third option. ( Imagine I hadn't asked the question. ) $\endgroup$ Commented Nov 23, 2013 at 12:24
7
$\begingroup$

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

$\endgroup$
1
  • $\begingroup$ 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];] $\endgroup$ Commented Nov 23, 2013 at 13:21
3
$\begingroup$

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

$\endgroup$
1
$\begingroup$
☺ = (♯ = #; ♯[[#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}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.