# [Python-ideas] Proposal: A Reduce-Map Comprehension and a "last" builtin

Danilo J. S. Bellini danilo.bellini at gmail.com
Mon Apr 16 18:02:59 EDT 2018

```On 16 April 2018 at 10:49, Peter O'Connor <peter.ed.oconnor at gmail.com>
wrote:

> Are you able to show how you'd implement the moving average example with
>

Sure! The single pole IIR filter you've shown is implemented here:
https://github.com/danilobellini/pyscanprev/blob/master/examples/iir-filter.rst

I tried:
>
>     @enable_scan("average")
>     def exponential_moving_average_pyscan(signal, decay, initial=0):
>         yield from ((1-decay)*(average or initial) + decay*x for x in
> signal)
>
>
>     smooth_signal_9 = list(exponential_moving_average_pyscan(signal,
> decay=decay))[1:]
>
> Which almost gave the right result, but seemed to get the initial
> conditions wrong.
>

I'm not sure what you were expecting. A sentinel as the first "average"
value?

Before the loop begins, this scan-generator just echoes the first input,
like itertools.accumulate.
That is, the first value this generator yields is the first "signal" value,
which is then the first "average" value.

To put an initial memory state, you should do something like this (I've
removed the floating point trailing noise):

>>> from pyscanprev import enable_scan, prepend
>>>
>>> @enable_scan("y")
>>> def iir_filter(signal, decay, memory=0):
...     return ((1 - decay) * y + decay * x for x in prepend(memory,
signal))
...
>>> list(iir_filter([1, 2, 3, 2, 1, -1, -2], decay=.1, memory=5))
[5, 4.6, 4.34, 4.206, 3.9854, 3.68686, 3.218174, 2.6963566]

In that example, "y" is the "previous result" (a.k.a. accumulator, or what