2012-06-10 2 views
4

Можно создать дубликат:
Rolling or sliding window iterator in PythonНайти Последовательные Комбинации

Я новичок в программировании и учусь Python. Я ищу эффективный/pythonic способ решить проблему.

Мне нужна функция, которая возвращает список итераций, содержащих комбинации родительского итеративного, если элементы в комбинации выглядят одинаково последовательно, как исходный родительский итерабельный.

Я не уверен, что «последовательный», если правильное слово, чтобы описать это понятие как «последовательное», как правило, означает «тот же самый элемент повторяется». например [1,1,1], 'ааа', и т.д ...

Я имею в виду, что данный список [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

Выглядит хорошо для меня. Я не думаю, что это правильное слово. То, что вы делаете, возвращает все _последовательности_ заданной длины заданной последовательности. –

+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)))) 

Soo много i s ...

Тем не менее, это один должен работать на любой итерацию (но может быть медленнее простые последовательности, такие как списки или строки).

+0

Приятный и элегантный :) –

3

Ваше решение в порядке. Вы могли бы немного сократить его немного. Например:

def subsequences(iterable, length): 
    return [iterable[i: i + length] for i in xrange(len(iterable) - length + 1)] 
Смежные вопросы