【问题标题】:Cumulatively add numbers with python's map function用python的map函数累加数字
【发布时间】:2018-03-21 00:33:57
【问题描述】:

朋友们好,我想做一个手术,我相信我可以用地图解决这个问题。

以下操作实际上可以正常工作。但我想做点不一样的。

当它增加时,18 将是 19。但是当下一个值出现时,它现在将被收集到 19。

在这个例子中,我想要的输出是:

>> [18,18,18,19,19,21]

这是我能做的:

def sum(x):
    return x+18

new_list = list(map(sum, [0,0,0,1,0,2]))

>> [18, 18, 18, 19, 18, 20]

【问题讨论】:

  • 首先,将您的函数命名为sum,并隐藏该名称的内置函数,这很令人困惑。
  • 但同时,我认为你想要的是accumulate,而不是map。您确实想添加一个起始值,但有两种简单的方法可以做到这一点:(1)在调用 accumulate 之前将起始值链接到输入,然后在输出中跳过它,或者(2)复制“大致等效于“文档中的代码并编写您自己的版本,该版本将起始值作为附加参数。
  • @abarnert:虽然itertools.accumulate 在这里不是一个选项,因为 OP 使用的是 2.7(accumulate 是在 3.2 中添加的)。所以你需要使用map 和一个有状态的映射函数(例如,一个实现__call__ 的类将保持运行总和)。
  • @ShadowRanger 或者您可以从 3.2 文档中复制 accumulate“大致等效”代码,该代码在 2.7 中有效。 (我被他明确调用list(map(…)) 所愚弄,这在 2.7 中毫无意义……)

标签: python arrays python-2.7


【解决方案1】:

使用 2.7 中reduce 函数怎么样? reduce 通常与 map 结合使用,在经过一定数量的地图转换后聚合列表。

这是我的 3.5 版本,如果与 2.7 不同,应该很接近:

startVal =  18
myList   =  [0,0,0,1,0,2]
accumulator = reduce((lambda x, y: ( x + [y + (0 if len(x) == 0 else x[-1])])), myList, [])  
[startVal + v for v in accumulator]

>> [18, 18, 18, 19, 19, 21]

我正在利用添加列表(连接)将后续值附加到初始化程序中定义的空列表。有一点条件,因为您无法获取空列表的最后一个条目。

【讨论】:

    【解决方案2】:

    尝试用map 做你想做的事需要给函数添加某种“记忆”——它必须知道它到目前为止做了什么,所以它知道下一步该做什么。

    可以通过使用闭包或使用带有__call__ 方法的类来做到这一点。但有一种更简单的方法。

    您正在寻找的几乎正是accumulate 函数。唯一的区别是您要提供一个起始值。 (当然,accumulate 实际上并不在 2.7 的 stdlib 中;您需要从 PyPI 的反向端口中获取它。)

    您可以通过三种明显的方式来处理它:

    • accumulate,然后将您的起始值添加到每个元素。
    • chain 输入之前的起始值,然后是 accumulate,然后是 next(或 islice)以跳过输出中的额外值。
    • 获取accumulate 文档中的“大致等效”示例代码并对其进行修改以获取起始值。

    让我们做最后一个——它可能是最重的选项,但你可以从中学到最多的东西,而且即使在 2.7 中也可以在没有任何反向移植的情况下工作:

    def accumulate(iterable, func=operator.add, start=0):
        'Return running totals'
        it = iter(iterable)
        total = start
        try:
            total += next(it)
        except StopIteration:
            return total
        yield total
        for element in it:
            total = func(total, element)
            yield total
    

    与文档中的原始代码相比,我所做的只是添加一个新参数,设置 total = start,并更改对第一个元素或空可迭代对象的特殊处理。你显然可以简化事情(如果我们有一个起始值,我们甚至不需要对空输入进行特殊处理),或者让事情变得更有趣(默认为没有起始值而不是 0,所以 @987654334 @ 适用于不能与 int 互操作的类型,就像 itertools 中的那样)等等,但这是一个简单的起点。

    现在:

    >>> new_list = accumulate([0,0,0,1,0,2], start=18)
    >>> new_list
    [18, 18, 18, 19, 18, 20]
    

    【讨论】:

      猜你喜欢
      • 2012-09-24
      • 2023-03-23
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 2013-05-20
      • 1970-01-01
      相关资源
      最近更新 更多