2012-06-10 179 views
4

可能重复:
Rolling or sliding window iterator in Python查找连续组合

我新的编程和正在学习Python的。我正在寻找解决问题的高效/ pythonic方法。

我想要一个函数返回一个包含父可迭代组合的可迭代列表,只要组合中的元素与原始父可迭代的顺序看起来是相同的连续顺序。

我不确定如果“连续”,如果将这个概念描述为“连续”的正确词语通常意味着'重复相同的元素'。例如[1,1,1], 'AAA',等...

我的意思是给出的列表[1,2,3,4,5]:

[1,2,3]是连续但[1,2,4]不是。 (是否有这句话吗?)

这里有一个功能consecutive_combinations()我创建和预期的行为:

def consecutive_combinations(iterable, consec): 
    begin = 0 
    chunks = len(iterable) + 1 - consec 
    return [iterable[x + begin: x + consec] for x in xrange(chunks)] 

def test(): 
    t = (1,2,3,4,5) 
    s = "The quick brown fox jumps over the lazy dog." 
    CC = consecutive_combinations 
    assert CC(t, 2) == [(1, 2), (2, 3), (3, 4), (4, 5)] 
    assert CC(t, 3) == [(1, 2, 3), (2, 3, 4), (3, 4, 5)] 
    assert CC(t, 4) == [(1, 2, 3, 4), (2, 3, 4, 5)] 
    assert CC(t, 5) == [(1, 2, 3, 4, 5)] 
    assert CC(s, 3) == ['The', 'he ', 'e q', ' qu', 'qui', 'uic', 'ick', 'ck ', 'k b', ' br', 'bro', 'row', 'own', 'wn ', 'n f', ' fo', 'fox', 'ox ', 'x j', ' ju', 'jum', 'ump', 'mps', 'ps ', 's o', ' ov', 'ove', 'ver', 'er ', 'r t', ' th', 'the', 'he ', 'e l', ' la', 'laz', 'azy', 'zy ', 'y d', ' do', 'dog', 'og. '] 
    assert CC('', 3) == [] 
    print "All tests passed!" 

test() 

这是一个有效的解决方案?在itertools或其他预构建模块中是否会有这样的事情?

+1

看起来不错。我不认为这种组合是正确的词。你正在做的是返回给定序列给定长度的所有_subsequences_。 –

+1

Ruby被称为'Enumerable#each_slice' –

+1

@JoelCornett:实际上,它们是*子字符串*,而不是*子序列*;子序列不一定是连续的。请注意,在大多数编程语言中,字符串在理论计算机科学中的含义更广泛。 –

回答

5

我喜欢务实zip方法:

n = 3 
s = "The quick brown fox jumps over the lazy dog." 
zip(*(s[i:] for i in xrange(n))) 

这不是超高效,它仅适用于序列,但往往不够它的工作。

相应itertools解决方案是上面的一个非常简单的转换:

from itertools import izip, islice, tee 

def slices(iterable, n): 
    return izip(*(islice(it, i, None) for i, it in enumerate(tee(iterable, n)))) 

洙许多i小号...

然而,这一个应该可迭代的工作(但可能是比较慢诸如列表或字符串的简单序列)。

+0

不错,优雅:) –

3

您的解决方案很好。你可以稍微缩短一点。例如:

def subsequences(iterable, length): 
    return [iterable[i: i + length] for i in xrange(len(iterable) - length + 1)]