Пропустить первую запись для цикла в Python?

187

В Python, как мне сделать что-то вроде:

for car in cars:
   # Skip first and last, do work for rest
Роландо
источник
4
Я новичок, но я использовал for n, i in enumerate(cars): if n!= 0: do something to i. логика в том , что она добавляет «счетчик» для каждого значения , которое вы можете целевую например , с if n == some_value. в этом примере он будет делать что-то для каждого экземпляра i, кроме первого.
user1063287

Ответы:

268

Другие ответы работают только для последовательности.

Для любой итерации, чтобы пропустить первый элемент:

itercars = iter(cars)
next(itercars)
for car in itercars:
    # do work

Если вы хотите пропустить последний, вы можете сделать:

itercars = iter(cars)
# add 'next(itercars)' here if you also want to skip the first
prev = next(itercars)
for car in itercars:
    # do work on 'prev' not 'car'
    # at end of loop:
    prev = car
# now you can do whatever you want to do to the last one on 'prev'
AGF
источник
1
Смотрите также Sven Marnach «сек ответ
AGF
2
Я обнаружил, что выполнение cars.pop (0) и cars.pop () работает хорошо.
dreamwork801
@ dreamwork801 Мой ответ и ответ Свена, который я связываю в первом комментарии, работают для любых итеративных, даже бесконечных, поскольку они не требуют операции O (n) над данными перед началом итерации. Ваше предложение и предложение Абхита работают только для последовательностей, а не для повторения.
agf
356

Чтобы пропустить первый элемент в Python, вы можете просто написать

for car in cars[1:]:
    # Do What Ever you want

или пропустить последний элемент

for car in cars[:-1]:
    # Do What Ever you want

Вы можете использовать эту концепцию для любой последовательности.

Abhijit
источник
52
Не для всех итераций , но для всех последовательностей .
Свен Марнах
2
Как насчет использования памяти? Делает ли срез новую копию подпоследовательности?
Вояджер
@Voyager Да, он делает новую копию.
Шринивас Редди Татиарти,
27

Лучший способ пропустить первый пункт (ы):

from itertools import islice
for car in islice(cars, 1, None):
    # do something

islice в этом случае вызывается с начальной точкой 1 и конечной точкой None, что означает конец итератора.

Чтобы иметь возможность пропустить элементы с конца итерируемого, вам нужно знать его длину (всегда возможно для списка, но не обязательно для всего, что вы можете повторять). например, islice (cars, 1, len (cars) -1) пропустит первый и последний элементы в списке автомобилей.

Роу Шенберг
источник
Посмотрите на ответ Свена (недооцененный). Он охватывает пропуск произвольного числа элементов в начале и / или конце любого итерируемого с использованием isliceдовольно хорошо, не зная длины или хранения в памяти больше элементов одновременно, чем это абсолютно необходимо.
августа
Ответ Свена фактически сохранит весь итератор в памяти - collection.deque будет проходить через итератор. Попробуйте сделать что-то вроде collection.deque (xrange (10000000)). Нет необходимости хранить все целые в памяти, если вы хотите пропустить первый элемент ...
Roee Shenberg
2
Это isliceто, что передается deque, а не весь итератор, и это только длина количества элементов, которые нужно пропустить в конце. Он не хранит весь итератор в памяти.
agf
26

Вот более общая функция генератора, которая пропускает любое количество элементов от начала и конца итерируемого:

def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    for x in itertools.islice(it, at_start):
        pass
    queue = collections.deque(itertools.islice(it, at_end))
    for x in it:
        queue.append(x)
        yield queue.popleft()

Пример использования:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
Свен Марнах
источник
Может быть, хотите добавить быстрый путь для at_end == 0.
AGF
collection.deque (...) немедленно пройдет через итератор. Это означает, что пропуск (xrange (10000000), 1) займет много памяти, хотя на самом деле это не должно быть.
Роуи Шенберг
4
@RoeeShenberg: skip(xrange(10000000), 1)будет использовать at_end=0, поэтому параметр to deque()будет islice(it, 0), который будет потреблять только ноль элементов it. Это не займет много памяти.
Свен Марнах
8
for item in do_not_use_list_as_a_name[1:-1]:
    #...do whatever
KurzedMetal
источник
3
Не используйте listв качестве имени переменной
Abhijit
ОП хочет пропустить только первый элемент. почему: -1?
luke14free
6
Это на самом деле не зарезервировано ; имя listможет быть связано. Вот почему вы не должны , а не можете использовать его.
ОАО
@ luke14free, вопрос говорит, что пропустить первый элемент, но его комментарий к коду подразумевает, что он действительно хочет пропустить первый и последний.
JerseyMike
@ luke14free Это то, что говорит заголовок, а не то, что он напечатал внутри кода: «пропустить, если первый или последний»
KurzedMetal
4

Пример:

mylist=['one'.'two','three'.'four'.'five']
for i in mylist[1:]:
   print(i)

В индексе Python, начиная с 0, мы можем использовать оператор нарезки для выполнения манипуляций в итерации.

for i in range(1,-1):
Тоно Куриакосе
источник
3

Основано на Ответе @SvenMarnach, но немного проще и без использования deque

>>> def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    it = itertools.islice(it, at_start, None)
    it, it1 = itertools.tee(it)
    it1 = itertools.islice(it1, at_end, None)
    return (next(it) for _ in it1)

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
>>> list(skip(range(10), at_start=2, at_end=5))
[2, 3, 4]

Также обратите внимание, на основании моего timeitрезультата, это немного быстрее, чем решение deque

>>> iterable=xrange(1000)
>>> stmt1="""
def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    it = itertools.islice(it, at_start, None)
    it, it1 = itertools.tee(it)
    it1 = itertools.islice(it1, at_end, None)
    return (next(it) for _ in it1)
list(skip(iterable,2,2))
    """
>>> stmt2="""
def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    for x in itertools.islice(it, at_start):
        pass
    queue = collections.deque(itertools.islice(it, at_end))
    for x in it:
        queue.append(x)
        yield queue.popleft()
list(skip(iterable,2,2))
        """
>>> timeit.timeit(stmt = stmt1, setup='from __main__ import iterable, skip, itertools', number = 10000)
2.0313770640908047
>>> timeit.timeit(stmt = stmt2, setup='from __main__ import iterable, skip, itertools, collections', number = 10000)
2.9903135454296716
Abhijit
источник
Используя tee(), вы все еще создаете весь список в памяти для генератора, верно? (твое it1)
Jabberwockey
2

Ну, ваш синтаксис не совсем Python для начала.

Итерации в Python заканчиваются содержимым контейнеров (ну, технически это итераторы), с синтаксисом for item in container. В этом случае контейнером является carsсписок, но вы хотите пропустить первый и последний элементы, что означает cars[1:-1](списки Python начинаются с нуля, отрицательные числа отсчитываются с конца, и: синтаксис разбивается на части).

Так ты хочешь

for c in cars[1:-1]:
    do something with c
Эндрю Джаффе
источник
4
Это не будет работать с итерацией (например, генератором), только с последовательностью.
Роуи Шенберг
2

Альтернативный метод:

for idx, car in enumerate(cars):
    # Skip first line.
    if not idx:
        continue
    # Skip last line.
    if idx + 1 == len(cars):
        continue
    # Real code here.
    print car
Банан
источник
2

Вот мой предпочтительный выбор. Это не требует добавления многого в цикл, и использует только встроенные инструменты.

Идти от:

for item in my_items:
  do_something(item)

чтобы:

for i, item in enumerate(my_items):
  if i == 0:
    continue
  do_something(item)
maninthecomputer
источник
1

Если carsэто последовательность, которую вы можете просто сделать

for car in cars[1:-1]:
    pass
Правин Голлакота
источник
1

more_itertoolsПроект распространяется itertools.isliceобрабатывать отрицательные индексы.

пример

import more_itertools as mit

iterable = 'ABCDEFGH'
list(mit.islice_extended(iterable, 1, -1))
# Out: ['B', 'C', 'D', 'E', 'F', 'G']

Таким образом, вы можете элегантно применить элементы среза между первым и последним элементами итерируемого элемента:

for car in mit.islice_extended(cars, 1, -1):
    # do something
pylang
источник
0

Я делаю это так, хотя это выглядит как хак, оно работает каждый раз:

ls_of_things = ['apple', 'car', 'truck', 'bike', 'banana']
first = 0
last = len(ls_of_things)
for items in ls_of_things:
    if first == 0
        first = first + 1
        pass
    elif first == last - 1:
        break
    else:
        do_stuff
        first = first + 1
        pass
DMB
источник