如何根据列表中项目的多个结果计算列表?
How to calculate a list based on multiple results from items in a list?
我有一个列表 A=[a,b,c,d]
。我需要根据 A
.
中每个项目之间的操作计算一个新列表 B
B= [a, b-(a), c-(a+(b-a)), d-(a+(b-a)+(c-(a+(b-a)))) ]
是否有 Pythonic 的方式来做到这一点?列表 A 并不总是一个包含 4 项的列表,因此解决方案需要推广到任意长度的列表。提前致谢。
请注意,您列表的表达式可以简化为:
B = [a, b-a, c-b, d-c]
考虑到这一点,我们可以使用列表理解:
[y - x for x, y in zip([0] + data, data)]
例如,
data = [1, 2, 7, 6]
result = [y - x for x, y in zip([0] + data, data)]
print(result)
输出:
[1, 1, 5, -1]
正如评论中的人所建议的,这是最简单、最快的解决方案:
A = [5, 9, 3, 8]
B = [x - y for x, y in zip(A, [0] + A)]
这输出:
B
[5, 4, -6, 5]
你所有的项都抵消了(c-(a+(b-a))
简化为c - b
,d-(a+(b-a)+(c-(a+(b-a))))
简化为d - c
),所以这里真正的算法是每个项都等于匹配项减去先前项。这大大简化了事情:
B = [A[0]] # Initial term has no prior to subtract from it
B += [x - y for x, y in zip(A[1:], A)] # All other terms computed by subtracting term n - 1 from term n
如果你想 one-line 这个(忽略导入)你可以插入一个虚拟 0
来获得第一个元素的结果而不显式 special-casing 它:
from itertools import chain # At top of file
B = [x - y for x, y in zip(A, chain([0], A))]
如果您喜欢使用 map
和朋友进行微优化,您可以将后者替换为:
from operator import sub # At top of file
B = [*map(sub, A, chain([0], A))]
并将所有工作推送到C层(没有per-element字节码执行)。
你也可以这样做
A = [1,2,3,4]
B = [A[0]]+[A[i+1]-A[i] for i in range(len(A)-1)]
两个不假设事物“抵消”的解决方案(因为对于像 float
和 Counter
这样的标准类型来说,这已经是错误的,如下所示)。
如果我理解正确,第一个 B-value 应该是第一个 A-value 然后每个下一个 B-value 应该总是下一个 A-value 减去总和所有以前的 B-value s。一种方法:
B = []
for a in A:
if not B:
b = sumB = a
else:
b = a - sumB
sumB = sumB + b
B.append(b)
有趣的是使用 itertools.accumulate
和 operator.sub
:
B = A[:1]
B += map(sub, A[1:], accumulate(B))
测试:
A = [31, 41, 59, 26]
reference [31, 10, 18, -33]
subtract_neighbors correct [31, 10, 18, -33]
loop correct [31, 10, 18, -33]
fun correct [31, 10, 18, -33]
A = [1, 1, 1e-20, 1e-20]
reference [1, 0, -1.0, 1e-20]
subtract_neighbors wrong [1, 0, -1.0, 0.0]
loop correct [1, 0, -1.0, 1e-20]
fun correct [1, 0, -1.0, 1e-20]
A = [Counter(), Counter({None: 1}), Counter(), Counter({None: 1})]
reference [Counter(), Counter({None: 1}), Counter(), Counter()]
subtract_neighbors wrong [Counter(), Counter({None: 1}), Counter(), Counter({None: 1})]
loop correct [Counter(), Counter({None: 1}), Counter(), Counter()]
fun correct [Counter(), Counter({None: 1}), Counter(), Counter()]
执行上述检查的代码 (Try it online!):
def reference(A):
a, b, c, d = A
return [a, b-(a), c-(a+(b-a)), d-(a+(b-a)+(c-(a+(b-a)))) ]
def subtract_neighbors(A):
a, b, c, d = A
return [a, b-a, c-b, d-c]
def loop(A):
B = []
for a in A:
if not B:
b = sumB = a
else:
b = a - sumB
sumB = sumB + b
B.append(b)
return B
def fun(A):
B = A[:1]
B += map(sub, A[1:], accumulate(B))
return B
from collections import Counter
from itertools import accumulate
from operator import sub
funcs = [
reference,
subtract_neighbors,
loop,
fun,
]
tests = [
[31, 41, 59,26],
[1, 1, 1e-20, 1e-20],
[Counter(), Counter([None])] * 2,
]
for A in tests:
print(' A =', A)
for func in funcs:
result = func(A)
if func is reference:
expect = result
correctness = ' '
else:
correctness = 'correct' if result == expect else 'wrong '
print(f'{func.__name__:19}', correctness, result)
print()
我有一个列表 A=[a,b,c,d]
。我需要根据 A
.
B
B= [a, b-(a), c-(a+(b-a)), d-(a+(b-a)+(c-(a+(b-a)))) ]
是否有 Pythonic 的方式来做到这一点?列表 A 并不总是一个包含 4 项的列表,因此解决方案需要推广到任意长度的列表。提前致谢。
请注意,您列表的表达式可以简化为:
B = [a, b-a, c-b, d-c]
考虑到这一点,我们可以使用列表理解:
[y - x for x, y in zip([0] + data, data)]
例如,
data = [1, 2, 7, 6]
result = [y - x for x, y in zip([0] + data, data)]
print(result)
输出:
[1, 1, 5, -1]
正如评论中的人所建议的,这是最简单、最快的解决方案:
A = [5, 9, 3, 8]
B = [x - y for x, y in zip(A, [0] + A)]
这输出:
B
[5, 4, -6, 5]
你所有的项都抵消了(c-(a+(b-a))
简化为c - b
,d-(a+(b-a)+(c-(a+(b-a))))
简化为d - c
),所以这里真正的算法是每个项都等于匹配项减去先前项。这大大简化了事情:
B = [A[0]] # Initial term has no prior to subtract from it
B += [x - y for x, y in zip(A[1:], A)] # All other terms computed by subtracting term n - 1 from term n
如果你想 one-line 这个(忽略导入)你可以插入一个虚拟 0
来获得第一个元素的结果而不显式 special-casing 它:
from itertools import chain # At top of file
B = [x - y for x, y in zip(A, chain([0], A))]
如果您喜欢使用 map
和朋友进行微优化,您可以将后者替换为:
from operator import sub # At top of file
B = [*map(sub, A, chain([0], A))]
并将所有工作推送到C层(没有per-element字节码执行)。
你也可以这样做
A = [1,2,3,4]
B = [A[0]]+[A[i+1]-A[i] for i in range(len(A)-1)]
两个不假设事物“抵消”的解决方案(因为对于像 float
和 Counter
这样的标准类型来说,这已经是错误的,如下所示)。
如果我理解正确,第一个 B-value 应该是第一个 A-value 然后每个下一个 B-value 应该总是下一个 A-value 减去总和所有以前的 B-value s。一种方法:
B = []
for a in A:
if not B:
b = sumB = a
else:
b = a - sumB
sumB = sumB + b
B.append(b)
有趣的是使用 itertools.accumulate
和 operator.sub
:
B = A[:1]
B += map(sub, A[1:], accumulate(B))
测试:
A = [31, 41, 59, 26]
reference [31, 10, 18, -33]
subtract_neighbors correct [31, 10, 18, -33]
loop correct [31, 10, 18, -33]
fun correct [31, 10, 18, -33]
A = [1, 1, 1e-20, 1e-20]
reference [1, 0, -1.0, 1e-20]
subtract_neighbors wrong [1, 0, -1.0, 0.0]
loop correct [1, 0, -1.0, 1e-20]
fun correct [1, 0, -1.0, 1e-20]
A = [Counter(), Counter({None: 1}), Counter(), Counter({None: 1})]
reference [Counter(), Counter({None: 1}), Counter(), Counter()]
subtract_neighbors wrong [Counter(), Counter({None: 1}), Counter(), Counter({None: 1})]
loop correct [Counter(), Counter({None: 1}), Counter(), Counter()]
fun correct [Counter(), Counter({None: 1}), Counter(), Counter()]
执行上述检查的代码 (Try it online!):
def reference(A):
a, b, c, d = A
return [a, b-(a), c-(a+(b-a)), d-(a+(b-a)+(c-(a+(b-a)))) ]
def subtract_neighbors(A):
a, b, c, d = A
return [a, b-a, c-b, d-c]
def loop(A):
B = []
for a in A:
if not B:
b = sumB = a
else:
b = a - sumB
sumB = sumB + b
B.append(b)
return B
def fun(A):
B = A[:1]
B += map(sub, A[1:], accumulate(B))
return B
from collections import Counter
from itertools import accumulate
from operator import sub
funcs = [
reference,
subtract_neighbors,
loop,
fun,
]
tests = [
[31, 41, 59,26],
[1, 1, 1e-20, 1e-20],
[Counter(), Counter([None])] * 2,
]
for A in tests:
print(' A =', A)
for func in funcs:
result = func(A)
if func is reference:
expect = result
correctness = ' '
else:
correctness = 'correct' if result == expect else 'wrong '
print(f'{func.__name__:19}', correctness, result)
print()