我想计算python中几个列表的平均值。这些列表包含数字作为字符串。空字符串不为零,表示缺少值。
我能想到的最好的就是这个。是否更优雅,简洁&有效的写作方式?
num = ['1', '2', '', '6']
total = sum([int(n) if n else 0 for n in num])
length = sum([1 if n else 0 for n in num])
ave = float(total)/length if length > 0 else '-'
P.S。我正在使用Python 2.7.x,但欢迎使用Python 3.x的配方
答案 0 :(得分:4)
num = ['1', '2', '', '6']
L = [int(n) for n in num if n]
ave = sum(L)/float(len(L)) if L else '-'
或
num = ['1', '2', '', '6']
L = [float(n) for n in num if n]
avg = sum(L)/len(L) if L else '-'
答案 1 :(得分:3)
在Python 3.4中使用statistics 库:
from statistics import mean
num = ['1', '2', '', '6']
ave = mean(int(n) if n else 0 for n in num)
答案 2 :(得分:1)
您可以丢弃方括号。 sum
也接受生成器表达式:
total = sum(int(n) if n else 0 for n in num)
length = sum(1 if n else 0 for n in num)
由于生成器仅在需要时生成值,因此可以节省在内存中存储列表的昂贵成本。特别是如果你正在处理更大的数据。
答案 3 :(得分:1)
这是关于OP解决方案与aIKid解决方案与gnibbler解决方案的一些时间安排,使用1..9
(加上空字符串)和10个试验中的100,000个数字列表:
import timeit
setup = '''
from __main__ import f1, f2, f3, f4
import random
random.seed(0)
choices = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '']
num = [random.choice(choices) for _ in range(10**5)]
'''
def f1(num): # OP
total = sum([int(n) if n else 0 for n in num])
length = sum([1 if n else 0 for n in num])
ave = float(total)/length if length > 0 else '-'
return ave
def f2(num): # aIKid
total = sum(int(n) if n else 0 for n in num)
length = sum(1 if n else 0 for n in num)
ave = float(total)/length if length > 0 else '-'
return ave
def f3(num): # gnibbler 1
L = [int(n) for n in num if n]
ave = sum(L)/float(len(L)) if L else '-'
return ave
def f4(num): # gnibbler 2
L = [float(n) for n in num if n]
ave = sum(L)/float(len(L)) if L else '-'
return ave
number = 10
things = ['f1(num)', 'f2(num)', 'f3(num)', 'f4(num)']
for thing in things:
print(thing, timeit.timeit(thing, setup=setup, number=number))
结果:
f1(num) 1.8177659461490339 # OP
f2(num) 2.0769015213241513 # aIKid
f3(num) 1.6350571199344595 # gnibbler 1
f4(num) 0.807052779158564 # gnibbler 2
看起来使用float
的gnibbler解决方案是最快的。
答案 4 :(得分:0)
一种不同的方法
num = ['1', '2', '', '6']
total = reduce(lambda acc, x: float(acc) + (float(x) if x else 0),num,0)
length = reduce(lambda acc, x: float(acc) + (1 if x else 0),num,0)
average = (',',total/length)[length > 0]