Как перебрать все, кроме последнего пункта списка?

160

Я хотел бы пройтись по списку, проверяя каждый элемент на соответствие следующему.

Есть ли способ, которым я могу перебрать все, кроме последнего элемента, использующего для х в у? Я бы предпочел сделать это без использования индексов, если смогу.

Заметка

freespace ответил на мой настоящий вопрос, поэтому я принял ответ, но SilentGhost ответил на вопрос, который я должен был задать.

Извиняюсь за путаницу.

Дэвид Сайкс
источник

Ответы:

316
for x in y[:-1]

Если yесть генератор, то вышеописанное не сработает.

свободное место
источник
Это отвечает на мой вопрос, спасибо, но я забыл спросить, как я получу предмет после x. Это возможно?
Дэвид Сайкс
3
- 1 Не думаю, что отвечу на вопрос. Он не сравнивает каждый элемент со следующим. - odwl 0 секунд назад
odwl
4
Я думаю, что сделал. Автор сказал, что хотел бы сделать X, затем спросил, как он может сделать Y. Я ответил, как он может сделать Y. То, что он принял мой ответ, будет означать, что я ответил на заданный им вопрос, если не на вопрос, который он действительно хотел задать. Аскер может опустить этот ответ.
свободное пространство
7
То, что ОП должен был задать еще один вопрос в первом, не означает, что его вопрос и этот ответ не очень полезны для других. +1
проф. Фалькен
1
Вы упоминаете, что это не работает для генераторов. Какая альтернатива, когда yгенератор?
Joost
50

Самый простой способ сравнить элемент последовательности со следующим:

for i, j in zip(a, a[1:]):
     # compare i (the current) to j (the following)
SilentGhost
источник
15
Это отвечает на вопрос, который я хотел бы задать. Спасибо
Дэвид Сайкс
3
На самом деле, вы можете опустить первый фрагмент, так как zip усекает длинный список до длины более короткого. Это сэкономит вам одно создание списка. (На всякий случай, если вы имеете дело с огромными списками. Но в этом случае вы должны следовать подходу Антса Аасмы, который ничего не копирует.)
Байер
19

Если вы хотите получить все элементы в последовательности пар, используйте этот подход (парная функция из примеров в модуле itertools).

from itertools import tee, izip, chain

def pairwise(seq):
    a,b = tee(seq)
    b.next()
    return izip(a,b)

for current_item, next_item in pairwise(y):
    if compare(current_item, next_item):
        # do what you have to do

Если вам нужно сравнить последнее значение с каким-то особым значением, соедините это значение до конца

for current, next_item in pairwise(chain(y, [None])):
Муравьи Аасма
источник
обратите внимание, что использование next для теней имен переменных встроено
SilentGhost
1
Лично я не возражаю против того, чтобы скрывать менее используемые встроенные функции, когда область действия переменной мала, а имя хорошо для удобства чтения. Тем не менее отредактировал имена переменных, чтобы сохранить хорошие методы кодирования.
Муравьи Аасма
5

если бы вы имели в виду сравнение n-го элемента с n + 1-м элементом в списке, вы также можете сделать с

>>> for i in range(len(list[:-1])):
...     print list[i]>list[i+1]

обратите внимание, что там нет жесткого кодирования. Это должно быть хорошо, если вы не чувствуете иначе.

Perpetualcoder
источник
3
Вы можете заменить len (list [: - 1]) на len (list) - 1, чтобы избежать копирования списка. И избегайте использования переменной с именем list ...
Реми Бланк
2

Чтобы сравнить каждый элемент со следующим в итераторе без создания списка:

import itertools
it = (x for x in range(10))
data1, data2 = itertools.tee(it)
data2.next()
for a, b in itertools.izip(data1, data2):
  print a, b
odwl
источник
2
это именно то, что было предложено Антсом Aasma stackoverflow.com/questions/914715/…
SilentGhost
1

Это отвечает тому, что должен был задать OP , то есть перебирает список, сравнивающий последовательные элементы (отличный ответ SilentGhost ), но обобщенный для любой группы ( n-грамм ): 2, 3, ... n:

zip(*(l[start:] for start in range(0, n)))

Примеры:

l = range(0, 4)  # [0, 1, 2, 3]

list(zip(*(l[start:] for start in range(0, 2)))) # == [(0, 1), (1, 2), (2, 3)]
list(zip(*(l[start:] for start in range(0, 3)))) # == [(0, 1, 2), (1, 2, 3)]
list(zip(*(l[start:] for start in range(0, 4)))) # == [(0, 1, 2, 3)]
list(zip(*(l[start:] for start in range(0, 5)))) # == []

Пояснения:

  • l[start:] генерирует список / генератор, начиная с индекса start
  • *listили *generator: передает все элементы в функцию включения, zipкак если бы она была написанаzip(elem1, elem2, ...)

Примечание:

AFAIK, этот код настолько ленив, насколько это возможно. Не проверено.

juanmirocks
источник