Итерация по всем парам последовательных элементов в списке
Учитывая список
l = [1, 7, 3, 5]
Я хочу перебрать все пары последовательных элементов списка (1,7), (7,3), (3,5)
, т.е.
for i in xrange(len(l) - 1):
x = l[i]
y = l[i + 1]
# do something
Я хотел бы сделать это более компактно, например
for x, y in someiterator(l): ...
Есть ли способ сделать это, используя встроенные итераторы Python? Я уверен, что модуль itertools
должен иметь решение, но я просто не могу понять это.
Ответы
Ответ 1
Просто используйте zip
>>> l = [1, 7, 3, 5]
>>> for first, second in zip(l, l[1:]):
... print first, second
...
1 7
7 3
3 5
Как было предложено, вы можете использовать функцию izip
в itertools
для очень длинных списков, где вы не хотите создавать новый список.
import itertools
for first, second in itertools.izip(l, l[1:]):
...
Ответ 2
Посмотрите pairwise
на рецепты itertools: http://docs.python.org/2/library/itertools.html#recipes
Цитата оттуда:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
Общая версия
Общая версия, которая дает кортежи любого заданного положительного натурального размера, может выглядеть так:
def nwise(iterable, n=2):
iters = tee(iterable, n)
for i, it in enumerate(iters):
next(islice(it, i, i), None)
return izip(*iters)
Ответ 3
Я бы создал генератор grouper
, как этот
def grouper(input_list, n = 2):
for i in xrange(len(input_list) - (n - 1)):
yield input_list[i:i+n]
Пример прогона 1
for first, second in grouper([1, 7, 3, 5, 6, 8], 2):
print first, second
Выход
1 7
7 3
3 5
5 6
6 8
Пример прогона 1
for first, second, third in grouper([1, 7, 3, 5, 6, 8], 3):
print first, second, third
Выход
1 7 3
7 3 5
3 5 6
5 6 8
Ответ 4
Вы можете использовать zip
.
>>> list(zip(range(5), range(2, 6)))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
Как и молния, он создает пары. Итак, чтобы смешивать ваши два списка, вы получаете:
>>> l = [1,7,3,5]
>>> list(zip(l[:-1], l[1:]))
[(1, 7), (7, 3), (3, 5)]
Затем повторение выполняется как
for x, y in zip(l[:-1], l[1:]):
pass
Ответ 5
То, что ниже, очень просто/читаемо и выполняет эту работу, также, вероятно, наиболее эффективно.
Преобразовать список в генератор (или лучше начать с итератора, чтобы играть с ним):
gen = (x for x in l)
Преобразуйте его в пары:
[(x, gen.next()) for x in gen]
Это все, что вам нужно.
Конечно, лучше сделайте его генератором и прочитайте его, как вам нужно:
( (x, gen.next()) for x in gen)