¿Saltar la primera entrada para for loop en python?

187

En python, ¿cómo hago algo como:

for car in cars:
   # Skip first and last, do work for rest
Rolando
fuente
44
Soy un novato, pero he estado usando for n, i in enumerate(cars): if n!= 0: do something to i. la lógica es que agrega un 'contador' a cada valor al que luego puede apuntar, por ejemplo, con if n == some_value. en este ejemplo, haría algo en cada instancia de i, excepto en la primera.
user1063287

Respuestas:

268

Las otras respuestas solo funcionan para una secuencia.

Para cualquier iterable, para omitir el primer elemento:

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

Si desea omitir el último, puede hacer:

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
fuente
1
También vea la respuesta de Sven Marnach
agf
2
Descubrí que hacer cars.pop (0) y cars.pop () funciona bien.
dreamwork801
@ dreamwork801 Mi respuesta y la de Sven, que enlace en el primer comentario, funcionan para cualquier iteración, incluso infinita, ya que no requieren una operación O (n) en los datos antes de que comience la iteración. Su sugerencia, y la de Abhjit, ambas solo funcionan para secuencias, no iterables.
agf
356

Para omitir el primer elemento en Python, simplemente puede escribir

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

o para saltear el último elemento

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

Puede usar este concepto para cualquier secuencia.

Abhijit
fuente
52
No para todos los iterables , sino para todas las secuencias .
Sven Marnach
2
¿Qué tal el uso de la memoria? ¿Slice hace una nueva copia de la subsecuencia?
Voyager
@Voyager Sí, hace una nueva copia.
Srinivas Reddy Thatiparthy
27

La mejor manera de omitir los primeros elementos es:

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

islice en este caso se invoca con un punto de inicio de 1 y un punto final de Ninguno, lo que significa el final del iterador.

Para poder omitir elementos desde el final de un iterable, debe conocer su longitud (siempre posible para una lista, pero no necesariamente para todo lo que puede iterar). por ejemplo, islice (cars, 1, len (cars) -1) omitirá el primer y el último elemento de la lista de automóviles.

Roee Shenberg
fuente
Eche un vistazo a la respuesta de Sven (poco apreciada). Cubre omitir un número arbitrario de elementos al principio y / o al final de cualquier iterable utilizando islicebastante bien, sin conocer la longitud o almacenar más elementos en la memoria de una vez de lo absolutamente necesario.
agf
La respuesta de Sven en realidad almacenará todo el iterador en la memoria: collections.deque se ejecutará a través del iterador. Intente hacer algo como collections.deque (xrange (10000000)). No hay necesidad de almacenar todas las entradas en la memoria si desea omitir el primer elemento ...
Roee Shenberg
2
An islicees lo que se pasa al dequeiterador, no todo el iterador, y es solo la longitud del número de elementos que se omiten al final. No almacena todo el iterador en la memoria.
agf
26

Aquí hay una función de generador más general que omite cualquier número de elementos desde el principio y el final de un iterable:

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

Ejemplo de uso:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
Sven Marnach
fuente
Es posible que desee agregar una ruta rápida para at_end == 0.
agf
collections.deque (...) pasará inmediatamente por el iterador. Esto significa que omitir (xrange (10000000), 1) ocupará mucha memoria aunque realmente no debería.
Roee Shenberg
44
@RoeeShenberg: skip(xrange(10000000), 1)usará at_end=0, por lo que el parámetro to deque()será islice(it, 0), que solo consumirá cero elementos de it. Esto no ocupará mucha memoria.
Sven Marnach
8
for item in do_not_use_list_as_a_name[1:-1]:
    #...do whatever
KurzedMetal
fuente
3
No utilizar listcomo nombre de variable
Abhijit
el OP solo quiere omitir el primer elemento. por qué: -1?
luke14free
66
En realidad no está reservado ; el nombre listse puede volver a vincular. Es por eso que no deberías , en lugar de no poder , usarlo.
jscs
@ luke14free, la pregunta dice omitir el primer elemento, pero su comentario de código implica que realmente quiere omitir el primero y el último.
JerseyMike
@ luke14free eso es lo que dice el título, no lo que escribió dentro del código: "omitir si es el primero o el último"
KurzedMetal
3

Basado en la respuesta de @SvenMarnach, pero un poco más simple y sin usar 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]

También timeittenga en cuenta que, según mi resultado, esto es marginalmente más rápido que la solución de 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
fuente
Al usar tee(), todavía está creando una lista completa en la memoria para el generador, ¿verdad? (su it1)
Jabberwockey
3

Ejemplo:

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

En Python index start from 0, podemos utilizar el operador de corte para realizar manipulaciones en iteración.

for i in range(1,-1):
Tono Kuriakose
fuente
2

Bueno, para empezar, tu sintaxis no es realmente Python.

Las iteraciones en Python están sobre el contenido de los contenedores (bueno, técnicamente está sobre iteradores), con una sintaxis for item in container. En este caso, el contenedor es la carslista, pero desea omitir el primer y el último elemento, por lo que eso significa cars[1:-1](las listas de Python son de base cero, los números negativos cuentan desde el final y :está cortando la sintaxis.

Entonces quieres

for c in cars[1:-1]:
    do something with c
Andrew Jaffe
fuente
44
Esto no funcionará con un iterable (por ejemplo, un generador), solo con una secuencia.
Roee Shenberg
2

Un método alternativo:

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
Plátano
fuente
2

Aquí está mi opción preferida. No requiere agregar mucho al ciclo, y no usa nada más que herramientas integradas.

Ir desde:

for item in my_items:
  do_something(item)

a:

for i, item in enumerate(my_items):
  if i == 0:
    continue
  do_something(item)
maninthecomputer
fuente
1

Si carses una secuencia que puedes hacer

for car in cars[1:-1]:
    pass
Praveen Gollakota
fuente
1

El more_itertoolsproyecto se extiende itertools.islicepara manejar índices negativos.

Ejemplo

import more_itertools as mit

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

Por lo tanto, puede aplicarlo con elegancia elementos de corte entre el primer y el último elemento de un iterable:

for car in mit.islice_extended(cars, 1, -1):
    # do something
pylang
fuente
0

Lo hago así, aunque parece un truco, funciona siempre:

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
fuente