假设我有一组对象包含:(相对变化,变化时间):
(+1,0) (-1, 1) (+1,3) (+1, 3) (-1, 5) (+1, 9)
现在我想用绝对值替换相对变化,从0开始:
(1,0) (0, 1) (1,3) (2, 3) (1, 5) (2, 9)
0+1 0+1-1 0+1-1+1 ...
最好的方法是什么?是否有允许我
的Python函数答案 0 :(得分:2)
以下是如何使用列表解析执行此操作:
>>> data = [(+1,0), (-1, 1), (+1,3), (+1, 3), (-1, 5), (+1, 9)]
>>> [(sum(x[0] for x in data[:i+1]), data[i][1]) for i in range(len(data))]
[(1, 0), (0, 1), (1, 3), (2, 3), (1, 5), (2, 9)]
或稍微更高效(不会为每个值调用sum()
):
result = [data[0]]
for change, t in data[1:]:
result.append((result[-1][0]+change, t))
由于您说这些是对象,因此您可能需要使用属性get替换索引,例如x[0]
中的sum(x[0] for x in data[:i+1])
可能会变为x.change
。
答案 1 :(得分:0)
你可以使用列表理解来做这件事,但考虑到你的请求的具体条款,这对我来说似乎更像是一个生成器的工作。这是一个非常通用的解决方案,应该适用于序列和迭代器。它在传递给它的iterable上执行相当于Haskell的scanl
函数,并将可选的初始值作为最后一个参数。
第一个参数应该是一个带有两个参数的函数 - 当前的累积状态和序列中的下一个项 - 并返回下一个累积状态。它可以像operator.add
一样简单,也可以更复杂。
>>> def scan(f, seq, init=None):
... seq = iter(seq)
... state = seq.next() if init is None else init
... yield state
... for i in seq:
... state = f(state, i)
... yield state
累计求和(即三角数):
>>> import operator
>>> list(scan(operator.add, range(10)))
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
以不同的初始值开头:
>>> list(scan(operator.add, range(1, 10), 10))
[10, 11, 13, 16, 20, 25, 31, 38, 46, 55]
适用于您的问题:
>>> diffs = [(1, 0), (-1, 1), (1, 3), (1, 3), (-1, 5), (1, 9)]
>>> list(scan(lambda x, y: (x[0] + y[0], y[1]), diffs))
[(1, 0), (0, 1), (1, 3), (2, 3), (1, 5), (2, 9)]
具有不同的初始值,只是为了它的乐趣。
>>> list(scan(lambda x, y: (x[0] + y[0], y[1]), diffs, (5, -1)))
[(5, -1), (6, 0), (5, 1), (6, 3), (7, 3), (6, 5), (7, 9)]