Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
    
I made an error, but have edited it, sorry. –  ndroock1 Nov 23 '13 at 12:21
3  
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

2 Answers 2

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

share|improve this answer
    
I did not know about the function FlattenAt, I like the third option. ( Imagine I hadn't asked the question. ) –  ndroock1 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}}

share|improve this answer
    
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];] –  ndroock1 Nov 23 '13 at 13:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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