如何制作一个与 R 中的“Reduce”类似的“functools.reduce”实现?

问题描述 投票:0回答:2

这是一个使用

Reduce

的 R 示例
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`

上面的代码是按照游程长度对提取的唯一值进行排序,可以通过

rle(x)$values
轻松获得。


我知道Python中的

itertools.groupby
与R中的
rle
执行相同的操作,但是,我很好奇的是:是否有可能通过在Python中使用
functools.reduce
来获得高度相似的翻译实现相同的功能,例如

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)

但不幸的是,它给出了类似的错误

{
    "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"
}

我的问题是:Python 中是否有类似 R 代码的

reduce
的单行代码?

python r arrays reduce
2个回答
4
投票

您可以使用列表作为初始:

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]

请注意,您可以使用 groupby

 中的 
itertools
:


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

2
投票

这是另一个解决方案,只是为了强调差异。在 R 中,标量也是长度为 1 的向量,因此 tail() 或 c() 没有问题,而 Python 没有标量[-1] 或标量 + 列表的概念。

def foo(a,b):
  if (isinstance(a, int)): return [a]
  elif a[-1] != b:         return a + [b]
  else:                    return a

reduce(foo, x) 
[1, 2, 4, 10, 5, 7]
© www.soinside.com 2019 - 2024. All rights reserved.