【问题标题】:python : can reduce be translated into list comprehensions like map, lambda and filter?python:reduce 可以翻译成 map、lambda 和 filter 之类的列表理解吗?
【发布时间】:2014-08-16 02:52:30
【问题描述】:

在 python 中编程时,我现在通过使用列表推导来避免maplambdafilter,因为它更易于阅读且执行速度更快。但是reduce也可以替换吗?

例如一个对象有一个运算符union(),它作用于另一个对象a1.union(a2),并给出第三个相同类型的对象。

我有一个对象列表:

L = [a1, a2, a3, ...]

如何将所有这些对象的 union() 与列表推导式结合起来,相当于:

result = reduce(lambda a, b :a.union(b), L[1:], L[0])

【问题讨论】:

  • 在某些情况下:没有。但取决于。请提供您想到的具体查询
  • @sshashank124 - 有什么例子吗?
  • 集合并集是一个不好的例子,因为你可以简单地做result = set().union(*L),即使 L 是一个空列表,它也有工作的好处。无论如何,lambda a, b :a.union(b) 可以更简洁地写成set.union,因为在 python 中obj.method(args)cls.method(obj, args) 相同
  • Guido 说要使用 for 循环而不是 reduce。他不喜欢 FP 结构。

标签: python list reduce map-function


【解决方案1】:

不是真的。列表推导更类似于mapfilter

【讨论】:

    【解决方案2】:

    由于列表推导式定义会生成另一个列表,因此您不能使用它来生成单个值。不是。 (嗯...有this nasty trick 使用旧版本python 中泄露的实现细节可以做到这一点。我什至不打算在这里复制示例代码。不要这样做。)

    如果您担心reduce() 及其同类的风格方面,请不要担心。说出你的减少,你会没事的。所以虽然:

    all_union = reduce(lambda a, b: a.union(b), L[1:], L[0])
    

    不好,这个:

    from functools import reduce
    
    def full_union(input):
        """ Compute the union of a list of sets """
        return reduce(set.union, input[1:], input[0])
    
    result = full_union(L)
    

    很清楚。

    如果您担心速度,请查看toolzcytoolz 包,它们分别是“快速”和“非常快”。在大型数据集上,与列表推导相比,它们通常可以让您避免多次处理数据或一次将整个数据集加载到内存中。

    【讨论】:

    • 要使 reduce() 表达式本身可读,请使第一个参数不是 lambda。例如:reduce(set.union, <list of sets>) 有时这需要您在调用 reduce 之外的某个地方定义(并因此命名)运算符。
    【解决方案3】:

    reduce 是 Python 达人的not among the favored functions,这已经不是什么秘密了。

    一般来说,reduceleft fold on a list

    在 Python 中编写折叠在可迭代对象上向左或向右折叠在概念上很容易:

    def fold(func, iterable, initial=None, reverse=False):
        x=initial
        if reverse:
            iterable=reversed(iterable)
        for e in iterable:
            x=func(x,e) if x is not None else e
        return x
    

    如果没有一些残暴的 hack,这将无法在推导中复制,因为推导中没有累加器类型的函数。

    只需使用 reduce —— 或者写一个对你更有意义的。

    【讨论】:

      【解决方案4】:

      reduce 的一个常见用途是展平列表列表。您可以改用列表推导式。

      L = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
      

      减少

      from functools import reduce  # python 3
      flattened = reduce(lambda x, y: x + y, L)
      
      print(flattened)
      
      [1, 2, 3, 2, 3, 4, 3, 4, 5]
      

      与列表组合

      flattened = [item for sublist in L for item in sublist]
      
      print(flattened)
      
      [1, 2, 3, 2, 3, 4, 3, 4, 5]
      

      如果你的问题可以通过对扁平化列表进行操作来解决,这是一个有效的替代方法。对比给定示例的这些单行代码:

      all_union = reduce(lambda a, b: set(a).union(set(b)), L)
      
      {1, 2, 3, 4, 5}
      
      all_union = set([item for sublist in L for item in sublist])
      
      {1, 2, 3, 4, 5}
      

      【讨论】:

      • 使用sum(L, [])。也就是说,总和/列表推导会创建一个“完整”列表,而 reduce(operator.or_, map(set, L), set()) 不会。
      猜你喜欢
      • 2014-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      相关资源
      最近更新 更多