-
22-09-2019 - |
题
是否有一个功能已大大增强的方式来 建立一个列表,其中包含一个正在运行的平均 一些功能?
在阅读一个有趣的小块约 火星,黑盒,而柯西的分布, 我认为这将是有趣的计算正在运行的平均分配柯西我自己:
import math
import random
def cauchy(location, scale):
p = 0.0
while p == 0.0:
p = random.random()
return location + scale*math.tan(math.pi*(p - 0.5))
# is this next block of code a good way to populate running_avg?
sum = 0
count = 0
max = 10
running_avg = []
while count < max:
num = cauchy(3,1)
sum += num
count += 1
running_avg.append(sum/count)
print running_avg # or do something else with it, besides printing
我认为,这种方法的工作,但我很好奇如果有可能是一个更优雅的方式建立起来, running_avg
列于使用循环和计(例如 列表解析).
有一些相关的问题,但他们解决更为复杂的问题(很小的窗口大小、指数的加权)或者不具体到蟒蛇:
解决方案
你可以写一个发生器:
def running_average():
sum = 0
count = 0
while True:
sum += cauchy(3,1)
count += 1
yield sum/count
或者,给予发电机,用于柯西数字和实用功能,用于正在运行的总和生,你可以有一个整洁的发电机的表达:
# Cauchy numbers generator
def cauchy_numbers():
while True:
yield cauchy(3,1)
# running sum utility function
def running_sum(iterable):
sum = 0
for x in iterable:
sum += x
yield sum
# Running averages generator expression (** the neat part **)
running_avgs = (sum/(i+1) for (i,sum) in enumerate(running_sum(cauchy_numbers())))
# goes on forever
for avg in running_avgs:
print avg
# alternatively, take just the first 10
import itertools
for avg in itertools.islice(running_avgs, 10):
print avg
其他提示
你可以用协同程序.它们类似于发电机发电,但可以让你送值。协程中加入Python2.5,因此这不会的工作,在之前的版本。
def running_average():
sum = 0.0
count = 0
value = yield(float('nan'))
while True:
sum += value
count += 1
value = yield(sum/count)
ravg = running_average()
next(ravg) # advance the corutine to the first yield
for i in xrange(10):
avg = ravg.send(cauchy(3,1))
print 'Running average: %.6f' % (avg,)
作为一个列理解:
ravg = running_average()
next(ravg)
ravg_list = [ravg.send(cauchy(3,1)) for i in xrange(10)]
编辑:
- 使用
next()
功能来代替it.next()
法。这是如此,它还将与Python3.的next()
功能也已经回来了-移植到蟒蛇2.6+.
在Python2.5,你可以替换的电话it.next()
, 或定义next
功能的你自己。
(谢谢你亚当*帕金)
我有两个可能的解决方案。两者都是通用的运行平均功能工作的任何数字列表。(可以工作,与任何可迭代)
发生基于:
nums = [cauchy(3,1) for x in xrange(10)]
def running_avg(numbers):
for count in xrange(1, len(nums)+1):
yield sum(numbers[:count])/count
print list(running_avg(nums))
名单的理解基础的(真相同的代码作为早期):
nums = [cauchy(3,1) for x in xrange(10)]
print [sum(nums[:count])/count for count in xrange(1, len(nums)+1)]
发电机-compatabile发生基于:
编辑:这一次我只是测试,看看如果我能让我的解决方案兼容的发电机很容易地以及它的业绩。这是什么,我来了。
def running_avg(numbers):
sum = 0
for count, number in enumerate(numbers):
sum += number
yield sum/(count+1)
看到的绩效统计数据以下,值得的。
性能特征:
编辑:我还决定试验Orip趣的是使用多个发电机以看到影响的性能。
使用斑马旅行记和下面(1,000,000个迭代的3倍):
print "Generator based:", ', '.join(str(x) for x in Timer('list(running_avg(nums))', 'from __main__ import nums, running_avg').repeat())
print "LC based:", ', '.join(str(x) for x in Timer('[sum(nums[:count])/count for count in xrange(1, len(nums)+1)]', 'from __main__ import nums').repeat())
print "Orip's:", ', '.join(str(x) for x in Timer('list(itertools.islice(running_avgs, 10))', 'from __main__ import itertools, running_avgs').repeat())
print "Generator-compatabile Generator based:", ', '.join(str(x) for x in Timer('list(running_avg(nums))', 'from __main__ import nums, running_avg').repeat())
我得到以下结果:
Generator based: 17.653908968, 17.8027219772, 18.0342400074
LC based: 14.3925321102, 14.4613749981, 14.4277560711
Orip's: 30.8035550117, 30.3142540455, 30.5146529675
Generator-compatabile Generator based: 3.55352187157, 3.54164409637, 3.59098005295
看到的评论对代码:
Orip's genEx based: 4.31488609314, 4.29926609993, 4.30518198013
结果是在几秒钟内,并显示 LC 新的发电机兼容的发电机的方法是一致的速度更快,结果可能有所不同。我期待着巨大的差异之间我原来的发电机和一个新的事实是,总和不计算的飞行。
不隶属于 StackOverflow