Python3 中的单行减少 [英] one-liner reduce in Python3

查看:58
本文介绍了Python3 中的单行减少的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Python3 中,我正在寻找一种方法来在 一行 中计算一个在元素上两两调用的 lambda 函数.假设我想计算一个整数列表的 LCM,这可以在 Python2 中的一行:

In Python3, I am looking for a way to compute in one line a lambda function called on elements two by two. Let’s say I want to compute the LCM of a list of integers, this can be done in one line in Python2:

print reduce(lambda a,b: a * b // gcd(a, b), mylist)

是否可以在一行 Python3 中做同样的事情(暗示,没有 functools.reduce)?

Is it possible to do the same in one line Python3 (implied, without functools.reduce)?

在 Python3 中,我知道 filtermapreduce 已经消失了.我觉得我不再需要 filtermap 因为它们可以用 Python3 以更短、更清晰的方式编写,但我认为我可以找到 filtermap 的一个很好的替代品code>reduce 也是如此,除了我没有找到.我看过许多文章 建议 使用 functools.reduce明确写出累积循环",但我想在不导入 functools 的情况下在一行中完成.

In Python3 I know that filter, map and reduce are gone. I don’t feel I need filter and map anymore because they can be written in Python3 in a shorter and more clear fashion but I thought I could find a nice replacement for reduce as well, except I haven’t found any. I have seen many articles that suggest to use functools.reduce or to "write out the accumulation loop explicitly" but I’d like to do it without importing functools and in one line.

如果它更容易,我应该提到我使用的函数都是关联可交换.例如,对于列表 [1,2,3,4] 上的函数 f,如果它计算:

If it makes it any easier, I should mention I use functions that are both associative and commutative. For instance with a function f on the list [1,2,3,4], the result will be good if it either computes:

  • f(1,f(2,f(3,4)))
  • f(f(1,2),f(3,4))
  • f(f(3,f(1,4)),2)
  • 或任何其他订单

推荐答案

假设你有一个至少有一项的序列,你可以简单地递归定义 reduce 如下:

Assuming you have a sequence that is at least one item long you can simply define reduce recursivly like this:

def reduce(func, seq): return seq[0] if len(seq) == 1 else func(reduce(func, seq[:-1]), seq[-1])

长版会更易读:

def reduce(func, seq):
    if len(seq) == 1:
        return seq[0]
    else:
        return func(reduce(func, seq[:-1]), seq[-1])

然而,这是递归的,python 不太擅长递归调用(意味着速度慢,递归限制阻止处理超过 300 个项目的序列).一个更快的实现是:

However that's recursive and python isn't very good at recursive calls (meaning slow and the recursion limit prevents prosessing sequences longer than 300 items). A much faster implementation would be:

def reduce(func, seq):
    tmp = seq[0]
    for item in seq[1:]:
        tmp = func(tmp, item)
    return tmp

但是由于循环,它不能放在一行中.可以使用副作用解决:

But because of the loop it can't be put in one-line. It could be solved using side-effects:

def reduce(func, seq): d = {}; [d.__setitem__('last', func(d['last'], i)) if 'last' in d else d.__setitem__('last', i) for i in seq]; return d['last']

或:

def reduce(func, seq): d = {'last': seq[0]}; [d.__setitem__('last', func(d['last'], i)) for i in seq[1:]]; return d['last']

相当于:

def reduce(func, seq): 
    d = {} 
    for item in seq:
        if 'last' in d:
            d['last'] = func(d['last'], item)
        else:
            d['last'] = item
    return d['last']  # or "d.get('last', 0)"

那应该更快,但它并不完全是 Pythonic,因为单行实现中的列表理解只是因为副作用而被使用.

That should be faster but it's not exactly pythonic because the list-comprehension in the one-line implementation is just used because of the side-effects.

这篇关于Python3 中的单行减少的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆