Python在移动窗口中拆分字符串

14

我有一个包含数字的字符串,像这样 - digit = "7316717"

现在我想以这样的方式拆分字符串,使输出是一个每次移动3个数字的滑动窗口。所以我得到 -

["731", "316", "167", "671", "717"]

应该如何处理? 直接的方法是使用for循环并进行迭代。但我感觉一些内置的Python字符串函数可以用较少的代码实现这个功能。您知道这样的方法吗?

```python # Python代码示例
digit = "7316717" window = [digit[i:i+3] for i in range(len(digit)-2)] print(window) ```
输出:
```python ['731', '316', '167', '671', '717'] ```
5个回答

14

itertools examples中提供了window函数,可以实现这一功能:

from itertools import islice
def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result

使用示例:

>>> ["".join(x) for x in window("7316717", 3)]
['731', '316', '167', '671', '717']

1
窗口?我使用Python 2.6.1,在我的itertools实现中,我没有看到窗口。这里有什么我错过了吗? - Srikar Appalaraju
对于混淆我感到抱歉。它不是itertools的一部分。上面显示的window函数(取自链接文档)是使用islice()创建通用window函数的示例。 - Shawn Chin
itertoolsrecipes中有一种更加优雅的代码,叫做 pairwise - ovgolovin
3
pairwise 确实看起来更加舒适,但它是以 2 为幅度的滑动窗口硬编码的(因此是 pairwise)。我想它可以进行参数化,但这样可能不再那么舒适,并且由于它使用了 teezip,所以可能不如 window 配方高效。 - Shawn Chin
teeizip是用C语言编写的,因此它们非常快。愉悦感是个人品味问题,我认为 :) - ovgolovin

12
>>> s = "7316717"
>>> [s[i:i+3] for i in range(len(s)-2)]
['731', '316', '167', '671', '717']

3

itertools文档中有一个非常好的配对pairwise的方法。

为了使它适用于组中的n个元素,我进行了现代化改进,编写了以下代码:

from itertools import tee, izip

def window(iterable, n):
    els = tee(iterable, n)
    for i, el in enumerate(els):
        for _ in xrange(i):
            next(el, None)
    return izip(*els)


print(["".join(i) for i in window("2316515618", 3)])

Python 2.7


你说得对。这种方法比islice版本更令人愉悦。聪明地使用了teenext。+1 - Shawn Chin
与此处提出的解决方案相同:https://dev59.com/iGw15IYBdhLWcg3wG4AJ#6822907 感谢你们两个。我更喜欢@ovgolovin的“enumerate”版本。但是,您应该再花费一些空间,也许使用xrange而不是range - Dr. Jan-Philip Gehrcke
@Jan-PhilipGehrcke,请随意编辑我的回答。StackOverflow是一项协作工作,可能会帮助未来的其他人! - ovgolovin

0
digit = "7316717"
digit_sets = [digit[i:i+3] for i in range(len(digit)-2)]

0

在滑动窗口的最新示例中,Shawn使用了collections.deque

newest example
def sliding_window(iterable, n):
    # sliding_window('ABCDEFG', 4) -> ABCD BCDE CDEF DEFG
    it = iter(iterable)
    window = collections.deque(islice(it, n), maxlen=n)
    if len(window) == n:
        yield tuple(window)
    for x in it:
        window.append(x)
        yield tuple(window)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接