Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to replace each 0 with the preceding element in a list in an idiomatic way in Mathematica?
    primarykey
    data
    text
    <p>This is a fun little problem, and I wanted to check with the experts here if there is a better functional/Mathematica way to approach solving it than what I did. I am not too happy with my solution since I use big IF THEN ELSE in it, but could not find a Mathematica command to use easily to do it (such as <code>Select</code>, <code>Cases</code>, <code>Sow/Reap</code>, <code>Map</code>.. etc...)</p> <p>Here is the problem, given a list values (numbers or symbols), but for simplicity, lets assume a list of numbers for now. The list can contain zeros and the goal is replace the each zero with the element seen before it.</p> <p>At the end, <em>the list should contain no zeros in it</em>.</p> <p>Here is an example, given </p> <pre><code>a = {1, 0, 0, -1, 0, 0, 5, 0}; </code></pre> <p>the result should be</p> <pre><code>a = {1, 1, 1, -1, -1, -1, 5, 5} </code></pre> <p>It should ofcourse be done in the most efficient way.</p> <p>This is what I could come up with</p> <pre><code>Scan[(a[[#]] = If[a[[#]] == 0, a[[#-1]], a[[#]]]) &amp;, Range[2, Length[a]]]; </code></pre> <p>I wanted to see if I can use Sow/Reap on this, but did not know how.</p> <p><strong>question: can this be solved in a more functional/Mathematica way? The shorter the better ofcourse :)</strong></p> <p><strong>update 1</strong> Thanks everyone for the answer, all are very good to learn from. This is the result of speed test, on V 8.04, using windows 7, 4 GB Ram, intel 930 @2.8 Ghz:</p> <p>I've tested the methods given for <code>n</code> from <code>100,000</code> to <code>4 million</code>. The <code>ReplaceRepeated</code> method does not do well for large lists.</p> <p><strong>update 2</strong></p> <p>Removed earlier result that was shown above in update1 due to my error in copying one of the tests.</p> <p>The updated results are below. Leonid method is the fastest. Congratulation Leonid. A very fast method.</p> <p><img src="https://i.stack.imgur.com/YN2dq.png" alt="enter image description here"></p> <p>The test program is the following:</p> <pre><code>(*version 2.0 *) runTests[sizeOfList_?(IntegerQ[#] &amp;&amp; Positive[#] &amp;)] := Module[{tests, lst, result, nasser, daniel, heike, leonid, andrei, sjoerd, i, names}, nasser[lst_List] := Module[{a = lst}, Scan[(a[[#]] = If[a[[#]] == 0, a[[# - 1]], a[[#]]]) &amp;, Range[2, Length[a]]] ]; daniel[lst_List] := Module[{replaceWithPrior}, replaceWithPrior[ll_, n_: 0] := Module[{prev}, Map[If[# == 0, prev, prev = #] &amp;, ll] ]; replaceWithPrior[lst] ]; heike[lst_List] := Flatten[Accumulate /@ Split[lst, (#2 == 0) &amp;]]; andrei[lst_List] := Module[{x, y, z}, ReplaceRepeated[lst, {x___, y_, 0, z___} :&gt; {x, y, y, z}, MaxIterations -&gt; Infinity] ]; leonid[lst_List] := FoldList[If[#2 == 0, #1, #2] &amp;, First@#, Rest@#] &amp; @lst; sjoerd[lst_List] := FixedPoint[(1 - Unitize[#]) RotateRight[#] + # &amp;, lst]; lst = RandomChoice[Join[ConstantArray[0, 10], Range[-1, 5]], sizeOfList]; tests = {nasser, daniel, heike, leonid, sjoerd}; names = {"Nasser","Daniel", "Heike", "Leonid", "Sjoerd"}; result = Table[0, {Length[tests]}, {2}]; Do[ result[[i, 1]] = names[[i]]; Block[{j, r = Table[0, {5}]}, Do[ r[[j]] = First@Timing[tests[[i]][lst]], {j, 1, 5} ]; result[[i, 2]] = Mean[r] ], {i, 1, Length[tests]} ]; result ] </code></pre> <p>To run the tests for length 1000 the command is:</p> <pre><code>Grid[runTests[1000], Frame -&gt; All] </code></pre> <p>Thanks everyone for the answers.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload