Using Mathematica, I have a list:
l={0,0,0,1,2,0,0,0,1,0,0,0,2,0,0,0}
I want to apply a function to the above list to obtain the following:
{0,0,0,1,2,2,2,2,1,1,1,1,2,2,2,2}
Essentially I want to replace the runs of 0 values with runs of the same length, but using the value of the positive integer just preceding each run of 0s.
I thought I could do this easily with FoldList, but I can’t see my way through to a solution.
Many thanks.
Here is your test list:
The following solution will be reasonably efficient:
The way it works is the following: we use the fact that only the first matching rule is applied. The variable
nstores the last non-zero value encountered by the pattern-matcher during its run through the list. Initially it is set to zero. The first rule replaces0with the current value ofn. If it matches, replacement is made and the pattern-matcher goes on. If it does not match, then we have a non-zero value and the second rule applies, updating the value ofn. Since theSetassignment returns back the value, the non-zero element is simply placed back. The solution should have a linear complexity in the length of the list, and is IMO a good example of the occasional utility of side effects mixed with rules.EDIT
Here is a functional version:
One can check that the rule – based version is about 4 times faster for really large lists. However,
the advantage of this form is that it can easily be
Compile-d, providing extreme performance:The difference is several hundred times here, and about a hundred times faster than the rule-based solution. OTOH, rule-based solution will work also with symbolic lists, not necessarily integer lists.