## New developments [rasher][1] posted a new answer with clean and well performing code that caused me to look again at this problem. (It well deserves your vote.) I see now that there are good ways to approach this problem that haven't yet been fully developed. Fundamentally rasher's code operates by `Sort`, but I don't think even he realized this as `Riffle` et al are superfluous. We merely need `Ordering` and `Part` applied to joined lists of the correct order: oInsert[list_, val_, pos_] := Join[val, list][[ Ordering @ Join[pos, Range @ Length @ list] ]] In a way rasher solved the problem *twice*: `Riffle` and `sa[[ps]] = reps` already place the elements in the proper order; one merely needs to get rid of the zeros. We could use `DeleteCases` but pattern based methods are slow. Instead I reimplemented the `Riffle` operation in terms of `SparseArray`, but to make it efficient I had to be clever and unfortunately here that (so far) implies less clean code. saInsert[list_, val_, pos_] := With[{no = Length[list], ni = Length[val]}, SparseArray[ Automatic, {2, no + 1}, 0, {1, {{0, ni, no + ni}, pos ~Join~ Range[no] ~Partition~ 1}, val ~Join~ list} ]\[Transpose]["NonzeroValues"] ] This ugly bit of code manually constructs a two row `SparseArray`, the upper row being the insertion elements and the lower being the original list. It then transposes them, and extracts the `"NonzeroValues"`. (Despite the name these are actually the non-background values; this code still works correctly with zeros.) Rudimentary test of both new methods: oInsert[{a, b, c, d, e}, {W, X, Y, Z}, {1, 2, 4, 6}] saInsert[{a, b, c, d, e}, {W, X, Y, Z}, {1, 2, 4, 6}] > {W, a, X, b, c, Y, d, e, Z} > {W, a, X, b, c, Y, d, e, Z} I shall add timings for these functions later, but to summarize my early findings: - `multiInsert2` is still the fastest for a limited number of insertions into a long list - `saInsert` is superior to all other methods posted so far for a greater number of insertions into a packed list - `oInsert` is competitive with `saInsert` and `rashernator` on unpacked lists. It is faster than `rashernator` on packed lists. ---------- ## Original Method If your list is a vector (has no sub-lists) this is perhaps the simplest way, and likely competitively fast: m = origlist; m[[{1, 5}]] = {{r, x}, m[[{1, 5}]]}\[Transpose] Flatten[m] > {r, a, b, c, d, x, e, f, g} Edit: Ray Koopman points out that this method, by itself, does not handle an edge case in `Insert` where the position is one greater than the length of the list, i.e. `Insert[{1,2,3}, x, 4]`. This is accounted for in the function below by padding the list as required. If your list is not a vector (as defined above) we could use a different head for the inserted elements and then replace it with `Sequence` to effect a flatten. Here is a function that handles both cases, selecting between the methods for best performance: multiInsert[list_List, val_, pos_] /; Length@val == Length@pos := Module[{m = list, f, pad}, pad[x_] /; Max@pos == Length@list + 1 := AppendTo[m, x]; If[VectorQ[val] && VectorQ[list], pad[{ }]; m[[pos]] = Transpose @ {val, m[[pos]]}; Flatten[m], pad[f[]]; m[[pos]] = MapThread[f, {val, m[[pos]]}]; m /. f -> Sequence ] ] Input is a little different from yours: multiInsert[Range@15, {a, b, c}, {3, 7, 13}] > {1, 2, a, 3, 4, 5, 6, b, 7, 8, 9, 10, 11, 12, c, 13, 14, 15} ## Preallocate Method Nasser proposed a method of preallocating the array. This idea was promising if it could be optimized because a packed array could be preserved throughout the process theoretically reducing memory and computation time. His implementation was limited in performance because it used a tag that necessitated unpacking and because searching for that tag using `Position` is slow. Here is an implementation that directly calculates the runs of original values rather than tagging and finding them afterward. multiInsert2[list_, val_, pos_] /; Length@val == Length@pos := Module[{new, start, end, offset, n1, n2}, {n1, n2} = Length /@ {list, val}; new = ConstantArray[0, n1 + n2]; start = Prepend[pos, 1]; end = Append[pos - 1, n1]; offset = Range[0, n2]; MapThread[ new[[# ;; #2]] = list[[#3 ;; #4]]; &, {offset + start, offset + end, start, end} ]; new[[pos + Range[0, n2 - 1]]] = val; new ] This function appear to be best for a moderate number of insertions into a long list. (See below) ## Notes and timings Ray Koopman posted a very elegant method, which on reflection I've seen before though I cannot remember where. I voted for that method but there is reason to use the longer forms that belisarius and I proposed: speed on long lists. Every `Insert` operation reallocates the array which takes time proportional to the length of the list. As such, a method using `Fold` will slow down considerably when doing many insertions into a very long list. I will call Ray Koopman's code `foldInsert`: foldInsert[list_, val_, pos_] /; Length@val == Length@pos := Fold[ Insert[#1, #2[[2]], #2[[1]]] &, list, Reverse @ Sort @ Transpose @ {pos, val} ] And using this timing code for the three functions `multiInsert`, `multiInsert2`, `foldInsert`: timeAvg = Function[func, Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}], HoldFirst]; time[n_Integer, k_Integer, rand_: RandomInteger] := Module[{start, vals, pos}, start = Range@n; vals = rand[9, k]; pos = Sort @ RandomSample[start, k]; timeAvg @ #[start, vals, pos] & /@ {multiInsert, multiInsert2, foldInsert} ] With 3500 insertions into a length 5000 list: time[5000, 3500] > {0.0017968, 0.007368, 0.01372} With five insertions into a length 500,000 list: time[500000, 5] > {0.02432, 0.0006736, 0.001448} With 7500 insertions into the length 500,000 list: time[500000, 7500] > {0.03244, 0.01812, 5.038} All timings above were performing with integer into integer insertions. If inserting reals unpacking is necessary. Here are a few timings for that situation: time[150000, 50, RandomReal] time[150000, 500, RandomReal] time[150000, 5000, RandomReal] >{0.01372, 0.005488, 0.0624} >{0.01308, 0.007368, 0.592} >{0.01684, 0.01748, 8.658} [1]: https://mathematica.stackexchange.com/users/11467/rasher