# How to add zeros before and after each element in a list?

Given the list

{0.2, 0.5, 0.7}


my desired list is:

{0., 0.2, 0., 0., 0.5, 0., 0., 0.7, 0.}


Can it be done in a smarter way especially for a list with a much larger number (say 1000) of elements?

Upsample[{0.2, 0.5, 0.7}, 3, 2]


{0., 0.2, 0., 0., 0.5, 0., 0., 0.7, 0.}

(Thanks: corey979)

• @corey979, right; OPI thought OP wanted {0., 0.2, 0., 0.5, 0., 0.7, 0., 0.}:) thank you.
– kglr
Commented Jan 16, 2018 at 18:46

This should be fast:

addZeros[arr_] :=
Module[{res = ConstantArray[0, 3 Length[arr]]},
res[[2 ;; -2 ;; 3]] = arr;
res
]


If you use floating point numbers instead of integers, use 0. in ConstantArray instead of 0 for improved performance.

Here's a performance-focused version:

iAddZeros[arr_, z_] :=
Module[{res = ConstantArray[z, 3 Length[arr]]},
res[[2 ;; -2 ;; 3]] = arr;
res
]

addZeros[arr_ /; DeveloperPackedArrayQ[arr, Real]] := iAddZeros[arr, 0.]



Benchmark:

With[{arr = RandomReal[1, 100000]},
]
(* {0.00024, Null} *)

• Can your answer be generalized such that addZeros[arr_,n_]  returns {0., 0.2,0.2,0.2, 0., 0., 0.5,0.5,0.5, 0., 0., 0.7,0.7,0.7, 0.} for n=3? I am having a problem to do this using Span. Commented Jan 16, 2018 at 18:22
• You can assign three times, each time with a Span shifted by one. Not pretty, but if you only need 3, it'll work. Commented Jan 16, 2018 at 18:49
list = {0.2, 0.5, 0.7};
Riffle[ConstantArray[0., 2 Length[list]], list, {2, -2, 3}]

{0., 0.2, 0., 0., 0.5, 0., 0., 0.7, 0.}


If the list-elements should be repeated n times then

n = 3;
With[{z = ConstantArray[0., Length[list]]},
Flatten[{{z}, ConstantArray[list, n], {z}}, {3, 1, 2}]]

{0., 0.2, 0.2, 0.2, 0., 0., 0.5, 0.5, 0.5, 0., 0., 0.7, 0.7, 0.7, 0.}


Another option might be

lst = {0.2,0.5,0.7};
Flatten[{0.,#,0.}&/@lst]


Replace[{0.2, 0.5, 0.7}, x_ :>  Sequence[0, x, 0], 1]


{0, 0.2, 0, 0, 0.5, 0, 0, 0.7, 0}

Edit

As Alexy Popkov pointed out in a comment (and thanks!), it is safer to use rule-delayed as x is then effectively locally scoped,

 x = 100; Replace[{0.2, 0.5, 2}, x_ :> Sequence[0, x, 0], 1];


{0, 0.2, 0, 0, 0.5, 0, 0, 2, 0}

x = 100; Replace[{0.2, 0.5, 2}, x_ ->  Sequence[0, x, 0], 1]


{0, 100, 0, 0, 100, 0, 0, 100, 0}

• Or Cases[{0.2, 0.5, 0.7}, x_ -> Sequence[0, x, 0], 1] Commented Jan 17, 2018 at 1:05
• It is safer to use scoped version: Replace[{0.2, 0.5, 0.7}, x_ :> Sequence[0, x, 0], 1]. Commented Jan 17, 2018 at 2:17
• @AlexeyPopkov Thanks! I had naively assumed that x was scoped locally in both constructs. Commented Jan 17, 2018 at 12:49

Given a list of 1000 elements, say,

SeedRandom[42]; data = RandomReal[1., 1000];


there are many ways to do what you ask for. Here is one using Riffle.

augmented =
{0., Sequence @@ Riffle[data, Unevaluated @ Sequence[0., 0.]], 0.};


which produces

Short[augmented, 3]


{0., 0.425905, 0., 0., 0.391023, 0., 0., <2986>>, 0., 0., 0.185166,0., 0., 0.249098, 0.}

• The OP wants the first element also to be 0.. Commented Jan 16, 2018 at 16:23
• @AlexeyPopkov. Thanks for pointing that out. I have corrected my answer. Commented Jan 16, 2018 at 16:30
• OP also inserts 2 zeros in-between, not one. Commented Jan 16, 2018 at 16:33
• @AlexeyPopkov. Maybe I finally got it right this time? Commented Jan 16, 2018 at 19:36

Here is a soluton based on SparseArray. It's not as fast as Szabolcs' approach, though, even if one removes Normal.

Normal@SparseArray[
Transpose[3 Range[{Length[data]}] - 1] -> data,
{3 Length[data]},
0.
];

list = {0.2, 0.5, 0.7};

SequenceCases[list, {x_} :> Sequence @@ {0, x, 0}]

Cases[list, x_ :> Sequence @@ {0, x, 0}]

Sequence @@@   Transpose[{ConstantArray[0, Length@list], list,     ConstantArray[0, Length@list]}]

Sequence @@ ArrayPad[#, {1, 1}] & /@ List /@ list


{0, 0.2, 0, 0, 0.5, 0, 0, 0.7, 0}

Another method using Insert:

PositionsToInsert[list_] := Outer[List, Sequence @@@ MapAt[-#[[2 ;; -2]] &,
Array[Range[Length@list + 1] &, 2], {2}]]


Using PositionsToInsert with Insert:

Insert[#, 0, PositionsToInsert[#]] &@list

(*{0, 0.2, 0, 0, 0.5, 0, 0, 0.7, 0}*)


An example with another list:

list2 = {a, b, c, d, e};
Insert[#, 0, PositionsToInsert[#]] &@list2 === Cases[list2, x_ :> Sequence @@ {0, x, 0}]

(*True*)


Using Splice

list={0.2,0.5,0.7};

Take[Riffle[list, Splice[{0, 0}], {1, -1, 2}], {2, -2}];


Two more ways to achieve the requested result:

BlockRandom[

(* generate 1000 random number *)
rands = RandomReal[{-1,1},1000];

res1 = Flatten[

(* use Riffle *)
res2 = ReleaseHold[
Prepend[Append[Riffle[rands, Hold[Sequence[0, 0]]], 0], 0]] // RepeatedTiming // Short;

{res1, res2}, RandomSeeding->123654789]


On my machine the timings are more or less the same (with the second one probably a bit faster)

My slow and naive solution that's also somewhat easy to read:

SeedRandom[42]; data = RandomReal[1., 1000];
Flatten[Table[Prepend[Append[Take[data,i],0.],0.],{i,Length[data]}]]

list = {0.2, 0.5, 0.7};

list /. x_?NumberQ :> Splice[{0, x, 0}]

Flatten[Append[0] /@ Prepend[0] /@ List /@ list]


{0, 0.2, 0, 0, 0.5, 0, 0, 0.7, 0}

list = {0.2, 0.5, 0.7};


Using Cases

Cases[list, x_ :> Sequence[0., x, 0.]]


{0., 0.2, 0., 0., 0.5, 0., 0., 0.7, 0.}

Using SequenceReplace (new in 11.3)

SequenceReplace[list, {x_} :> Sequence[0., x, 0.]]


{0., 0.2, 0., 0., 0.5, 0., 0., 0.7, 0.}