连续切片可迭代

时间:2017-05-22 11:24:28

标签: python python-3.x slice iterable

假设我有一个迭代器

/Applications/Xcode8.3.app/Contents/Developer/Platforms/iPhoneOS.platform

我希望计算连续的平均值,并将它们存储在iterable元素

numbers = iter(range(100))

这可以通过将iterable转换为list / tuple并将其slices计算为

来完成
0., 0.5, ..., 49., 49.5

(有关docsfrom 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)

但这不是我所说的。

3 个答案:

答案 0 :(得分:2)

似乎没有标准方法可以获得iterableiterator / 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 Nelements重复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]