Insert at specific resulting positions?

I have an initial list:

list0 = {1,2,3,4,5};


and I want to insert {a,x} at specific positions {1,5}, which means that I want the resulting list to have a at position 1 and x at position 5. This is different from what Mathematica's Insert does, and what has been asked here before (Looking for a way to insert multiple elements into multiple positions simultaneously in a list). In my example, the output I expect is:

In[]: myInsert[list0, {a,x}, {1,5}]
Out[]: {a,1,2,3,x,4,5}


What's a clean way to do this? And what's a good name for this type of insertion?

Multidimensional version: Insert at specific resulting positions in multidimensional list?

• What would be the result of myInsert[list0,{a,x},{4,1}], {x,1,2,a,3,4,5} or {x,1,2,3,a,4,5} ? – andre314 Dec 4 '14 at 17:03
• @andre myInsert[list0,{a,x},{4,1}] should output {x,1,2,a,3,4,5}. The list of positions {4,1} gives the positions of the inserted elements in the resulting list. – becko Dec 4 '14 at 17:05
• @andre Thanks for pointing out that the positions list should be sorted ;) – becko Dec 4 '14 at 17:28
• related (newer) question mathematica.stackexchange.com/q/129294/2079 – george2079 Oct 22 '16 at 12:37

2 Answers

Fold[Insert[#, #2[[1]], #2[[2]]] &, list0, {{a, 1}, {x,5}}]
(* {a, 1, 2, 3, x, 4, 5} *)


Or, define a function:

insertF = Fold[Insert[#, #2[[1]], #2[[2]]] &, #,  SortBy[Transpose[{#2, #3}], Last]] &;
(* thanks: @becko *)

insertF[Range@5, {a, x}, {1, 4}]
(* {a, 1, 2, x, 3, 4, 5} *)
insertF[Range@5, {a, w, x}, {1, 5, 4}]
(* {a, 1, 2, x, w, 3, 4, 5} *)

• The line of code Fold[Insert[#, #2[[1]], #2[[2]]] &, list0, {{a, 1}, {x,5}}] gives what I want. However the function insertF as you defined it doesn't. In your example with the function, x should be inserted at position 4 of the resulting list. – becko Dec 4 '14 at 17:09
• In think the Accumulate@#3 is the problem. Replacing it with just #3 works. – becko Dec 4 '14 at 17:10
• @becko, you are right; still trying to fix it :). – kglr Dec 4 '14 at 17:12
• I think that insertF = Fold[Insert[#, #2[[1]], #2[[2]]] &, #, SortBy[Transpose[{#2, #3}], Last]] &; works. – becko Dec 4 '14 at 17:27
• @becko, oh, just saw the edit in your question... realized i was trying to solve the wrong question:) – kglr Dec 4 '14 at 17:38

I found a rather simple way to do what I want:

myInsert[list_, val_, pos_] :=
Insert[list, val, List /@ (Sort@pos - Range@Length@pos + 1)]


Example:

In[]:= myInsert[Range@5, x, {1, 5}]
Out[]= {x, 1, 2, 3, x, 4, 5}


However, this inserts only inserts copies of the same element, and I haven't come up with a good name for this yet.

• It appears that this answer is not quite what the question poser needs, since the Output does not match the desired Output. The problem with the proposed solution is that the counting of insertion index should occur BEFORE insertion of any elements, not AFTER. – David G. Stork Dec 4 '14 at 16:59
• @DavidG.Stork I disagree. This produces the desired output (I am the OP ;)). Please tell me why you think this is not consistent with what I asked. – becko Dec 4 '14 at 17:04
• You stated you wanted this output: {a,1,2,3,x,4,5} but the code above produced this output: {x,1,2,a,3,4,5}. @Andre asked my same question: 'What would be the result of myInsert[list0,{a,x},{4,1}], {x,1,2,a,3,4,5} or {x,1,2,3,a,4,5}?' – David G. Stork Dec 4 '14 at 18:32
• @DavidG.Stork Yes. As I explain in the answer, this method doesn't allow inserting multiple elements. It only inserts copies of the same element. Hence I obtain {x, 1, 2, 3, x, 4, 5} – becko Dec 4 '14 at 18:33
• The issue is not whether multiple elements can be inserted but instead the LOCATION of the insertions. As @Andre's question shows, there was an ambiguity about whether there should be TWO elements of list0 that separate the "x" and "a" or instead THREE elements that separate the "x" and "a". It seems, moreover, that there has been a change in the code from specifying insertion points as {1,4} to {1,5}, further complicating the discussion. – David G. Stork Dec 4 '14 at 18:46