# 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 Jan 16 '18 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. – Majis Jan 16 '18 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. – Szabolcs Jan 16 '18 at 18:49

Another option might be

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


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


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.. – Alexey Popkov Jan 16 '18 at 16:23
• @AlexeyPopkov. Thanks for pointing that out. I have corrected my answer. – m_goldberg Jan 16 '18 at 16:30
• OP also inserts 2 zeros in-between, not one. – Alexey Popkov Jan 16 '18 at 16:33
• @AlexeyPopkov. Maybe I finally got it right this time? – m_goldberg Jan 16 '18 at 19:36
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] – user1066 Jan 17 '18 at 1:05
• It is safer to use scoped version: Replace[{0.2, 0.5, 0.7}, x_ :> Sequence[0, x, 0], 1]. – Alexey Popkov Jan 17 '18 at 2:17
• @AlexeyPopkov Thanks! I had naively assumed that x was scoped locally in both constructs. – user1066 Jan 17 '18 at 12:49

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.
];


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]


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