Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
列表中滑动窗口对上的Pythonic迭代?_Python_List_Iteration_Itertools_List Manipulation - Fatal编程技术网

列表中滑动窗口对上的Pythonic迭代?

列表中滑动窗口对上的Pythonic迭代?,python,list,iteration,itertools,list-manipulation,Python,List,Iteration,Itertools,List Manipulation,在滑动对中迭代列表最有效的方法是什么?下面是一个相关的例子: >>> l ['a', 'b', 'c', 'd', 'e', 'f', 'g'] >>> for x, y in itertools.izip(l, l[1::2]): print x, y ... a b b d c f 这是成对的迭代,但我们如何在滑动对上得到迭代呢?表示成对的迭代: a b b c c d d e etc. 这是对的迭代,除了每次将对滑动1个元素而不是2个元素。谢谢。这

在滑动对中迭代列表最有效的方法是什么?下面是一个相关的例子:

>>> l
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> for x, y in itertools.izip(l, l[1::2]): print x, y
... 
a b
b d
c f
这是成对的迭代,但我们如何在滑动对上得到迭代呢?表示成对的迭代:

a b
b c
c d
d e
etc.

这是对的迭代,除了每次将对滑动1个元素而不是2个元素。谢谢。

这是我不久前为类似场景编写的一个小生成器:

def pairs(items):
    items_iter = iter(items)
    prev = next(items_iter)

    for item in items_iter:
        yield prev, item
        prev = item
那么:

for x, y in itertools.izip(l, l[1:]): print x, y

你可以做得更简单。只需压缩列表并将列表偏移1

In [4]: zip(l, l[1:])
Out[4]: [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('e', 'f'), ('f', 'g')]

不完全是最有效的,但非常灵活:

class SubsequenceIter(object):

    def __init__(self, iterable, subsequence_length):

        self.iterator = iter(iterable)
        self.subsequence_length = subsequence_length
        self.subsequence = [0]

    def __iter__(self):

        return self

    def next(self):

        self.subsequence.pop(0)
        while len(self.subsequence) < self.subsequence_length:
            self.subsequence.append(self.iterator.next())
        return self.subsequence

这里有一个用于任意大小滑动窗口的函数,它适用于迭代器/生成器以及列表

def sliding(seq, n):
  return izip(*starmap(islice, izip(tee(seq, n), count(0), repeat(None))))

Nathan的解决方案可能更有效。

通过在列表中添加两个后续条目定义的计时显示在下面,并按从快到慢的顺序排列

吉尔

杰夫·里迪

In [70]: timeit.repeat("for x,y in sliding(l,2): x+y", setup=setup, number=1000)
Out[70]: [1.2408790588378906, 1.2099130153656006, 1.207326889038086]
阿莱斯塔尼斯

In [66]: timeit.repeat("for i in range(0, len(l)-1): l[i] + l[i+1]", setup=setup, number=1000)
Out[66]: [1.3387370109558105, 1.3243639469146729, 1.3245630264282227]
奇穆利格

In [68]: timeit.repeat("for x,y in zip(l, l[1:]): x+y", setup=setup, number=1000)
Out[68]: [1.4756009578704834, 1.4369518756866455, 1.5067830085754395]
内森别墅美国酒店

In [63]: timeit.repeat("for x,y in pairs(l): x+y", setup=setup, number=1000)
Out[63]: [2.254757881164551, 2.3750967979431152, 2.302199125289917]
sr2222

请注意,重复次数减少了

In [60]: timeit.repeat("for x,y in SubsequenceIter(l,2): x+y", setup=setup, number=100)
Out[60]: [1.599524974822998, 1.5634570121765137, 1.608154058456421]
设置代码:

setup="""
from itertools import izip, starmap, islice, tee, count, repeat
l = range(10000)

def sliding(seq, n):
  return izip(*starmap(islice, izip(tee(seq, n), count(0), repeat(None))))

class SubsequenceIter(object):

    def __init__(self, iterable, subsequence_length):

        self.iterator = iter(iterable)
        self.subsequence_length = subsequence_length
        self.subsequence = [0]

    def __iter__(self):

        return self

    def next(self):

        self.subsequence.pop(0)
        while len(self.subsequence) < self.subsequence_length:
            self.subsequence.append(self.iterator.next())
        return self.subsequence

def pairs(items):
    items_iter = iter(items)
    prev = items_iter.next()

    for item in items_iter:
        yield (prev, item)
        prev = item
"""
setup=”“”
从itertools导入izip、星图、islice、T形三通、计数、重复
l=范围(10000)
def滑动(序号n):
返回izip(*星图(islice,izip(T形三通(序号,n),计数(0),重复(无)))
类子序列器(对象):
定义初始长度(自、可编辑、子序列长度):
self.iterator=iter(iterable)
self.subsequence\u length=subsequence\u length
self.subsequence=[0]
定义(自我):
回归自我
def next(自我):
self.subsequence.pop(0)
而len(self.subsequence)
无需导入,只要有对象列表或字符串,就可以进行导入;任何带有
var[index]
的内容。在python 3.6上测试

# This will create windows with all but 1 overlap
def ngrams_list(a_list, window_size=5, skip_step=1):
    return list(zip(*[a_list[i:] for i in range(0, window_size, skip_step)]))
for循环本身创建了一个字母表
a_列表
(如图所示
window=5
,OP希望
window=2

['ABCDEFGHIJKLMNOPQRSTUVWXYZ',
 'BCDEFGHIJKLMNOPQRSTUVWXYZ', 
 'CDEFGHIJKLMNOPQRSTUVWXYZ', 
 'DEFGHIJKLMNOPQRSTUVWXYZ',
 'EFGHIJKLMNOPQRSTUVWXYZ']
zip(*result\u of\u for\u loop)
将收集所有完整的垂直列作为结果。如果您想要少于所有,但只有一个重叠:

# You can sample that output to get less overlap:
def sliding_windows_with_overlap(a_list, window_size=5, overlap=2):
    zip_output_as_list = ngrams_list(a_list, window_size)])
    return zip_output_as_list[::overlap+1]
overlap=2
时,它跳过以
B
C
开头的列,并选择
D

[('A', 'B', 'C', 'D', 'E'),
 ('D', 'E', 'F', 'G', 'H'), 
 ('G', 'H', 'I', 'J', 'K'), 
 ('J', 'K', 'L', 'M', 'N'), 
 ('M', 'N', 'O', 'P', 'Q'), 
 ('P', 'Q', 'R', 'S', 'T'), 
 ('S', 'T', 'U', 'V', 'W'), 
 ('V', 'W', 'X', 'Y', 'Z')]

编辑:看起来这与@chmullig提供的类似,带有选项

这基本上是迭代器协议,只是作为生成器编写。为什么不将其作为自定义迭代器类(类似于
pairister
)?@sr2222--你可以这样做,但是为什么呢?虽然我没有做任何测试,但我有点怀疑这个类会快得多,而且生成器非常简单。这就是我要做的(+1)--虽然,我可能会避免使用非描述性变量
I
。相反,我可能会将其称为
items\u iter
或类似的东西--虽然这确实需要额外的18字节磁盘空间,但我认为它非常值得,因为它的清晰性:)非常密切相关:是的,唯一的区别是,在另一个问题中,他们希望第一对在位置0处有
None
。@NathanVillaescusa——是的,这就是为什么我没有把它标记为dupe。但我认为,总体思路仍然适用于各种答案。这要求iterable是可切片的——它不会与一般迭代器一起工作。Python 3没有
izip
,但有
zip\u最长的
。为了避免最后一对中出现空白点,我在itertools.zip_longest(l[:-1],l[1:]):print x,y@jtpereyda中使用了
来表示x,y,Python 3具有顶级函数
zip
,其作用与
itertools.izip
相同。如果您不想在最后一对中有一个空白点,可以使用@chmullig的答案。
# You can sample that output to get less overlap:
def sliding_windows_with_overlap(a_list, window_size=5, overlap=2):
    zip_output_as_list = ngrams_list(a_list, window_size)])
    return zip_output_as_list[::overlap+1]
[('A', 'B', 'C', 'D', 'E'),
 ('D', 'E', 'F', 'G', 'H'), 
 ('G', 'H', 'I', 'J', 'K'), 
 ('J', 'K', 'L', 'M', 'N'), 
 ('M', 'N', 'O', 'P', 'Q'), 
 ('P', 'Q', 'R', 'S', 'T'), 
 ('S', 'T', 'U', 'V', 'W'), 
 ('V', 'W', 'X', 'Y', 'Z')]