Search code examples
pythonrarraysreduce

How to make a `functools.reduce` implementation that looks similarly as `Reduce` in R?


Here is an R example of using Reduce

x <- c(1, 2, 2, 4, 10, 5, 5, 7)
Reduce(\(a, b) if (tail(a, 1) != b) c(a, b) else a, x) # equivalent to `rle(x)$values`

The code above is to sort out the extract unique values in terms of run length, which can be easily obtained by rle(x)$values.


I know in Python there is itertools.groupby that performs the same thing as rle in R, BUT, what I am curious about is: Is it possible to have a highly similar translation by using functools.reduce in Python to achieve the same functionality, say, for example

from functools import reduce
x = [1,2,2,4,10,5,5,7]
reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)

but which unfortunately gives errors like

{
    "name": "TypeError",
    "message": "'int' object is not subscriptable",
    "stack": "---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[58], line 4
      1 from functools import reduce
      2 x = [1,2,2,4,10,5,5,7]
----> 4 reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)

Cell In[58], line 4, in <lambda>(a, b)
      1 from functools import reduce
      2 x = [1,2,2,4,10,5,5,7]
----> 4 reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)

TypeError: 'int' object is not subscriptable"
}

My question is: Is there any one-liner of reduce in Python that looks like R code?


Solution

  • you could use a list as the initial:

    from functools import reduce
    x = [1,2,2,4,10,5,5,7]
    
    reduce(lambda a, b: a + [b] if a[-1]!= b else a, x, [x[0]])
    [1, 2, 4, 10, 5, 7]
    

    Note that you could use groupby from itertools:

    
    from itertools import groupby
    [i for i,j in groupby(x)]
    [1, 2, 4, 10, 5, 7]