9
$\begingroup$

I have a list like this:

l={{2,3},1,{4,7,2,1},3,{2,2,3,3},0,{4,4,2,1},4}

and I want to replace the natural numbers outside the sublists (at level 1) with an equal number of 0s:

replace[l]=={{2,3},0,{4,7,2,1},0,0,0,{2,2,3,3},{4,4,2,1},0,0,0,0}
$\endgroup$
2
  • 2
    $\begingroup$ Depend on @rhermans If[Head[#] === List, #, Splice@ ConstantArray[0, #]] & /@ l $\endgroup$
    – cvgmt
    Commented Feb 19, 2023 at 12:24
  • $\begingroup$ Variant on other answers: MapAt[Splice@ConstantArray[0, #]&, #, Position[#, _Integer, 1]]&@l $\endgroup$
    – user1066
    Commented Apr 6 at 14:10

7 Answers 7

11
$\begingroup$

Using Replace:

l = {{2, 3}, 1, {4, 7, 2, 1}, 3, {2, 2, 3, 3}, 0, {4, 4, 2, 1}, 4}

Replace[l, i_Integer :> Sequence @@ ConstantArray[0, i], 1]

Using SequenceReplace:

SequenceReplace[l, i : {_Integer} :> Sequence @@ ConstantArray[0, i]]

Using Sow/Reap:

First@Last@
  Reap@Scan[
    If[IntegerQ[#]
      , Sow[Splice@ConstantArray[0, #]]
      (*,Sow@Splice[Table[0,#]]*)
      , Sow@#] &, l
    , {1}
    ]

Using MapAt:

MapAt[Splice[Table[0, #]] &, l
 , Position[l, i_Integer, 1]
 ]

Result:

{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}

$\endgroup$
10
$\begingroup$

Similar with @rhermans

If[ListQ[#], #, Splice@ConstantArray[0, #]] & /@ l

{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}

$\endgroup$
10
$\begingroup$
l /. {x : {__Integer} :> x, i_Integer :> Splice[Table[0, i]]}
{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}

ReplaceAll >> Details:

ReplaceAll looks at each part of expr, tries all the rules on it, and then goes on to the next part of expr. The first rule that applies to a particular part is used; no further rules are tried on that part or on any of its subparts.

$\endgroup$
8
$\begingroup$

Another way to do this is to use SplitBy:

Join @@ (If[Length[Level[#, {-1}]] == 1, ConstantArray[0, #], #] & /@ SplitBy[l, Length])

(*{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}*)

Or using SplitBy and ReplaceAll:

Join @@ (SplitBy[l, Length] /. {{x_Integer} :> ConstantArray[0, x]})

(*{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}*)
$\endgroup$
3
$\begingroup$
list = {{2, 3}, 1, {4, 7, 2, 1}, 3, {2, 2, 3, 3}, 0, {4, 4, 2, 1}, 4};

Using SequenceCases and Splice (new in 12.1)

Catenate @ SequenceCases[list, {a_, b_} :> {a, Splice @ Table[0, b]}]

{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}

$\endgroup$
3
$\begingroup$
list = {{2, 3}, 1, {4, 7, 2, 1}, 3, {2, 2, 3, 3}, 0, {4, 4, 2, 1}, 4};

Using SubsetReplace (new in 12.1)

SubsetReplace[list, {a_Integer} :> Splice @ Table[0, a]]

{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}

$\endgroup$
2
$\begingroup$

Another way using ReplaceList:

ReplaceList[l, {___, a_List, b__Integer, ___} :> Splice@{a, Splice@Table[0, b]}]

{{2, 3}, 0, {4, 7, 2, 1}, 0, 0, 0, {2, 2, 3, 3}, {4, 4, 2, 1}, 0, 0, 0, 0}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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