Подтвердить что ты не робот

Pythonic способ перебора части списка

Я хочу перебрать все в списке, кроме первых нескольких элементов, например:

for line in lines[2:]:
    foo(line)

Это краткий, но копирует весь список, что не нужно. Я мог бы сделать:

del lines[0:2]
for line in lines:
    foo(line)

Но это изменяет список, что не всегда хорошо.

Я могу это сделать:

for i in xrange(2, len(lines)):
    line = lines[i]
    foo(line)

Но это просто грубо.

Лучше может быть следующее:

for i,line in enumerate(lines):
    if i < 2: continue
    foo(line)

Но это не так очевидно, как самый первый пример.

Итак: Каким образом это сделать так же очевидно, как и в первом примере, но не копирует список без необходимости?

4b9b3361

Ответ 2

Хотя itertools.islice представляется оптимальным решением для этой проблемы, так или иначе, дополнительный импорт просто кажется излишним для чего-то настолько простого.

Лично я нахожу решение enumerate прекрасно читаемым и сжатым - хотя я бы предпочел написать его вот так:

for index, line in enumerate(lines):
    if index >= 2:
        foo(line)

Ответ 3

Исходное решение в большинстве случаев является подходящим.

for line in lines[2:]:
    foo(line)

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

Ответ 4

def skip_heading( iterable, items ):
    the_iter= iter( iterable ):
    for i, e in enumerate(the_iter):
        if i == items: break
    for e in the_iter:
        yield e

Теперь вы можете for i in skip_heading( lines, 2 ): не беспокоиться.

Ответ 5

Вы можете создать вспомогательный генератор:

def rangeit(lst, rng):
  for i in rng:
    yield lst[i]

for e in rangeit(["A","B","C","D","E","F"], range(2,4)):
  print(e)

Ответ 6

for fooable in (line for i,line in enumerate(lines) if i >= 2):
    foo(fooable)

Ответ 7

Я предпочитаю использовать dropwhile. Он чувствует себя естественно после использования его в Haskell и некоторых других языках и кажется достаточно понятным. Вы также можете использовать его во многих других случаях, когда вы хотите найти более сложное условие триггера, чем индекс элемента для начала итерации.

from itertools import dropwhile

for item in dropwhile(lambda x: x[0] < 2, enumerate(lst)):
  # ... do something with item