¿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

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'

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.


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.


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]

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

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

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

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

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

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)


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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.