假设我有一个迭代器
/Applications/Xcode8.3.app/Contents/Developer/Platforms/iPhoneOS.platform
我希望计算连续的平均值,并将它们存储在iterable元素
中numbers = iter(range(100))
这可以通过将iterable转换为list
/ tuple
并将其slices计算为
0., 0.5, ..., 49., 49.5
(有关docs的from statistics import mean
# in cases with large or potentially infinite amounts of data
# this conversion will fail
numbers_list = list(numbers)
numbers_slices = (numbers_list[:end + 1] for end in range(len(numbers_list)))
mean_values = map(mean, numbers_slices)
功能的更多信息)
所以我的问题更为通用:有没有办法在不使用mean
/ list
包装的情况下使用标准库获取连续的iterable切片?
我们可以编写像
这样的实用功能tuple
然后
def get_slices(iterable):
elements = []
for element in iterable:
elements.append(element)
yield elements
但它看起来也很糟糕
P上。 S。:我知道计算像
这样的连续平均值会更好numbers_slices = get_slices(numbers)
mean_values = map(mean, numbers_slices)
但这不是我所说的。
答案 0 :(得分:2)
似乎没有标准方法可以获得iterable(iterator / list
/ tuple
/等)的连续切片
我发现的更好的方法是使用原始问题中的一点修改效用函数
def consecutive_slices(iterable):
elements = []
for element in iterable:
elements.append(element)
yield list(elements)
<强>修饰强>:
添加elements
的复制(顺便提一下doing that的方法很多),因为以前的版本是list
>>> numbers_slices = list(get_slices(numbers))
会向list
N
个elements
重复N
次,其中包含所有数字(例如>>> numbers_slices == [list(range(100))] * 100
True
等于100):
from itertools import (accumulate,
chain)
def consecutive_slices(iterable):
def collect_elements(previous_elements, element):
return previous_elements + [element]
return accumulate(chain(([],), iterable), collect_elements)
在写了更多内容后,我意识到这也可以使用itertools
module之类的
list
此处我们使用chain
作为初始切片添加空islice
,使用from itertools import islice
...
islice(consecutive_slices(range(10)), 1, None)
可以忽略结果
var file = getFoo(); // An in-memory file as a vinyl object.
return gulp.src(file) // What to do here? gulp.src only accepts globs.
.pipe(css(opts)) // (gulp-clean-css)
.pipe(gulp.dest('...'));
但将它作为一个切片似乎是合法的,因为空切片也是一个切片。
与之前的解决方案相比,这仍然是4行代码功能几乎完全相同,但更少“意大利面”IMO。
答案 1 :(得分:1)
你可以拥有一个直接yield
手段的生成器,其中局部变量包含运行总数和计数。 (实际上,您可以通过迭代enumerate(iterable)
并将1
添加到索引来免费获得计数。这是否足以提示?
答案 2 :(得分:0)
看看itertools.islice
Link
import itertools
def get_slices(iterable):
return map(lambda x: itertools.islice(iterable, x), xrange(len(iterable)))
如果您不知道长度,这里有一个缩小版本,内存非常低效:
from functools import reduce
numbers = (number for number in range(1,100))
mean = lambda x, y: (x+y)/float(2)
reduce(lambda x, y: x + [mean(x[-1], y)], numbers, [0])
[0.0, 0.5, 1.25, 2.125, 3.0625, 4.03125, 5.015625, 6.0078125, 7.00390625, 8.001953125, 9.0009765625, 10.00048828125, 11.000244140625, 12.0001220703125, 13.00006103515625, 14.000030517578125, 15.000015258789062, 16.00000762939453, 17.000003814697266, 18.000001907348633, 19.000000953674316, 20.000000476837158, 21.00000023841858, 22.00000011920929, 23.000000059604645, 24.000000029802322, 25.00000001490116, 26.00000000745058, 27.00000000372529, 28.000000001862645, 29.000000000931323, 30.00000000046566, 31.00000000023283, 32.000000000116415, 33.00000000005821, 34.000000000029104, 35.00000000001455, 36.000000000007276, 37.00000000000364, 38.00000000000182, 39.00000000000091, 40.000000000000455, 41.00000000000023, 42.000000000000114, 43.00000000000006, 44.00000000000003, 45.000000000000014, 46.00000000000001, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0]
所以,最后我们做的几乎和你的代码一样,所以你应该使用它或使用列表而不是生成器ande然后使用列表的切片(itertools.ilice
)< /强>
修改强>:
我一直在考虑这个问题,用Haskell
scanl
很容易解决,所以我对这个概念进行了解释并取得了很好的结果:
def scanl(f, g):
n = next(g)
yield n
for e in g:
n = f(n, e)
yield n
list(scanl(mean, number))
[0, 0.5, 1.25, 2.125, 3.0625, 4.03125, 5.015625, 6.0078125, 7.00390625, 8.001953125, 9.0009765625, 10.00048828125, 11.000244140625, 12.0001220703125, 13.00006103515625, 14.000030517578125, 15.000015258789062, 16.00000762939453, 17.000003814697266, 18.000001907348633, 19.000000953674316, 20.000000476837158, 21.00000023841858, 22.00000011920929, 23.000000059604645, 24.000000029802322, 25.00000001490116, 26.00000000745058, 27.00000000372529, 28.000000001862645, 29.000000000931323, 30.00000000046566, 31.00000000023283, 32.000000000116415, 33.00000000005821, 34.000000000029104, 35.00000000001455, 36.000000000007276, 37.00000000000364, 38.00000000000182, 39.00000000000091, 40.000000000000455, 41.00000000000023, 42.000000000000114, 43.00000000000006, 44.00000000000003, 45.000000000000014, 46.00000000000001, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0]