我有一个偶数浮点数列表:
[2.34,3.45,4.56,1.23,2.34,7.89,......]。
我的任务是计算1和2个元素的平均值,3和4,5和6等。在Python中执行此操作的简短方法是什么?
答案 0 :(得分:16)
data = [2.34, 3.45, 4.56, 1.23, 2.34, 7.89]
print [(a + b) / 2 for a, b in zip(data[::2], data[1::2])]
说明:
data[::2]
是元素2.34, 4.56, 2.34
data[1::2]
是元素3.45, 1.23, 7.89
zip
将它们合并为2个元组:(2.34, 3.45), (4.56, 1.23), (2.34, 7.89)
答案 1 :(得分:8)
如果名单不长,Paul Draper的回答很简单。如果 非常长,您可能需要考虑其他两个选项之一。
首先,使用迭代器,可以避免复制巨大的临时列表:
avgs = [(a + b) / 2 for a, b in zip(*[iter(data)]*2)]
这实际上是一样的,但懒惰,这意味着它只需要在内存中存储一个值(好吧,三个值-a,b和平均值)而不是全部他们。
iter(data)
为数据创建一个惰性迭代器。[iter(data)]*2
创建一个列表,其中包含对同一个迭代器的两个引用,因此当一个进程前进时,另一个也会进行。zip
和列表理解,保罗已经很好地解释了。 (在Python 2.x中,与{3.}相反,zip
并非懒惰,因此您需要使用itertools.izip
而不是zip
。)如果你实际上并不需要结果列表,只是你可以迭代的东西,将外部方括号更改为括号,它就变成了一个生成器表达式,这意味着它为你提供了一个迭代器而不是一个列表,并且你'根本不存储任何东西。
请注意,itertools
文档有grouper
的配方可以处理棘手的问题(您也可以在第三方模块more-itertools
中找到它),因此您可以只需编写grouper(data, 2)
而不是zip(*[iter(data)]*2)
,如果您经常这样做,这肯定会更具可读性。如果您需要更多说明,请参阅How grouper works。
或者,您可以使用NumPy数组而不是列表:
data_array = np.array(data)
然后你可以这样做:
avg_array = (data_array[::2] + data_array[1::2]) / 2
这不仅更简单(不需要显式循环),它的速度也提高了约10倍,并占用了大约1/4的内存。
如果你想把它推广到任意长度的组......
对于迭代器解决方案,它很简单:
[sum(group) / size for group in zip(*[iter(data)]*size)]
对于NumPy解决方案,它有点棘手。你必须动态地为data[::size]
,data[1::size]
,...,data[size-1::size]
上的迭代器创建一些东西,如下所示:
sum(data[x::size] for x in range(size)) / size
在NumPy中还有其他方法可以做到这一点,但只要size
不是太大,这就没问题了 - 它的优点是完全相同的技巧适用于Paul Draper的解决方案:
[sum(group) / size for group in zip(*(data[x::size] for x in range(size)))]
答案 2 :(得分:4)
s= [2.34, 3.45, 4.56, 1.23, 2.34, 7.89, ...]
res= [(s[i]+s[i+1])/2 for i in range(0, len(s)-1, 2)]
答案 3 :(得分:1)
使用 NumPy 找到连续两个值的平均值/平均值,这在时间和空间复杂度方面更有效:
data=np.array([1,2,3,4,5,6])
k=2 #In your case
data1=np.mean(data.reshape(-1, k), axis=1)
答案 4 :(得分:0)
只需使用索引即可完成任务。
举个简单的例子,
avg = []
list1 = [2.34, 3.45, 4.56, 1.23, 2.34, 7.89]
for i in range(len(list1)):
if(i+1 < len(list1):
avg.append( (list1[i] + list1[i+1]) / 2.0 )
avg2 = []
avg2 = [j for j in avg[::2]]
avg2就是你想要的。这可能很容易理解..