7
$\begingroup$

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?

$\endgroup$
9
$\begingroup$
Upsample[{0.2, 0.5, 0.7}, 3, 2]

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

(Thanks: corey979)

$\endgroup$
  • $\begingroup$ @corey979, right; OPI thought OP wanted {0., 0.2, 0., 0.5, 0., 0.7, 0., 0.}:) thank you. $\endgroup$ – kglr Jan 16 '18 at 18:46
6
$\begingroup$

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_ /; Developer`PackedArrayQ[arr, Real]] := iAddZeros[arr, 0.]

addZeros[arr_ /; Developer`PackedArrayQ[arr, Complex]] := iAddZeros[arr, 0. + 0. I]

addZeros[arr_] := iAddZeros[arr, 0]

Benchmark:

With[{arr = RandomReal[1, 100000]},
 addZeros[arr]; // RepeatedTiming
 ]
(* {0.00024, Null} *)
$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – Majis Jan 16 '18 at 18:22
  • $\begingroup$ You can assign three times, each time with a Span shifted by one. Not pretty, but if you only need 3, it'll work. $\endgroup$ – Szabolcs Jan 16 '18 at 18:49
5
$\begingroup$

Another option might be

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

Mathematica graphics

$\endgroup$
5
$\begingroup$
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.}
$\endgroup$
3
$\begingroup$

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

$\endgroup$
  • 1
    $\begingroup$ The OP wants the first element also to be 0.. $\endgroup$ – Alexey Popkov Jan 16 '18 at 16:23
  • $\begingroup$ @AlexeyPopkov. Thanks for pointing that out. I have corrected my answer. $\endgroup$ – m_goldberg Jan 16 '18 at 16:30
  • 2
    $\begingroup$ OP also inserts 2 zeros in-between, not one. $\endgroup$ – Alexey Popkov Jan 16 '18 at 16:33
  • $\begingroup$ @AlexeyPopkov. Maybe I finally got it right this time? $\endgroup$ – m_goldberg Jan 16 '18 at 19:36
3
$\begingroup$
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}

rather than (original answer):

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

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

$\endgroup$
  • $\begingroup$ Or Cases[{0.2, 0.5, 0.7}, x_ -> Sequence[0, x, 0], 1] $\endgroup$ – user1066 Jan 17 '18 at 1:05
  • 1
    $\begingroup$ It is safer to use scoped version: Replace[{0.2, 0.5, 0.7}, x_ :> Sequence[0, x, 0], 1]. $\endgroup$ – Alexey Popkov Jan 17 '18 at 2:17
  • $\begingroup$ @AlexeyPopkov Thanks! I had naively assumed that x was scoped locally in both constructs. $\endgroup$ – user1066 Jan 17 '18 at 12:49
3
$\begingroup$

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.
];
$\endgroup$
2
$\begingroup$

Two more ways to achieve the requested result:

BlockRandom[

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

 (* use PadLeft/Right *)
 res1 = Flatten[
   PadLeft[PadRight[{#}, 2], 3] & /@ rands] // RepeatedTiming // Short;

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

 {res1, res2}, RandomSeeding->123654789]

(see PadLeft, Riffle)

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

$\endgroup$
2
$\begingroup$

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]}]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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