Pular a primeira entrada no loop for em python?

187

Em python, como faço para algo como:

for car in cars:
   # Skip first and last, do work for rest
Rolando
fonte
4
Eu sou um novato, mas eu tenho usado for n, i in enumerate(cars): if n!= 0: do something to i. a lógica é que ele adiciona um 'contador' a cada valor que você pode segmentar, por exemplo if n == some_value. neste exemplo, faria algo para cada instância de i, exceto a primeira.
User1063287

Respostas:

268

As outras respostas funcionam apenas para uma sequência.

Para qualquer iterável, pule o primeiro item:

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

Se você quiser pular a última, você pode fazer:

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
fonte
1
Ver também Sven Marnach 's resposta
agf
2
Eu descobri que fazer cars.pop (0) e cars.pop () funciona bem.
dreamwork801
@ dreamwork801 Minhas respostas e as de Sven, que vinculo no primeiro comentário, funcionam para quaisquer iteráveis, mesmo infinitos, pois eles não exigem uma operação O (n) nos dados antes do início da iteração. Sua sugestão, e a de Abhjit, funcionam apenas para sequências, não iteráveis.
agf
356

Para pular o primeiro elemento do Python, você pode simplesmente escrever

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

ou para pular o último elem

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

Você pode usar esse conceito para qualquer sequência.

Abhijit
fonte
52
Não para todos os iterables , mas para todas as seqüências .
Sven Marnach 9/04
2
E quanto ao uso de memória? A fatia faz uma nova cópia da sub-sequência?
Voyager
@ Voyager Sim, ele faz uma nova cópia.
Srinivas Reddy Thatiparthy
27

A melhor maneira de pular os primeiros itens é:

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

O islice nesse caso é chamado com um ponto inicial de 1 e um ponto final de Nenhum, significando o final do iterador.

Para poder pular itens do final de uma iterável, você precisa saber o seu comprimento (sempre possível para uma lista, mas não necessariamente para tudo em que você pode iterar). por exemplo, islice (carros, 1, len (carros) -1) pulará o primeiro e o último itens da lista de carros.

Roee Shenberg
fonte
Dê uma olhada na resposta de Sven (subvalorizada). Ele cobre pular um número arbitrário de itens no início e / ou final de qualquer iterável usando islicemuito bem, sem saber o tamanho ou armazenar mais itens na memória ao mesmo tempo do que o absolutamente necessário.
agf
A resposta de Sven realmente armazenará o iterador inteiro na memória - collections.deque será executado no iterador. Tente fazer algo como collections.deque (xrange (10000000)). Não há nenhuma necessidade de armazenar todos os ints na memória se você quiser pular o primeiro item ...
Roee Shenberg
2
An isliceé o que é passado para o dequeiterador, não para todo, e é apenas o tamanho do número de itens a serem ignorados no final. Não armazena o iterador inteiro na memória.
amigos estão dizendo sobre agf
26

Aqui está uma função geradora mais geral que ignora qualquer número de itens do início e do final de um iterável:

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

Exemplo de uso:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
Sven Marnach
fonte
Pode querer adicionar um caminho rápido para at_end == 0.
perfil completo
collections.deque (...) passará imediatamente pelo iterador. Isso significa que ignorar (xrange (10000000), 1) consumirá muita memória, mesmo que realmente não deva.
Roee Shenberg 04/12/12
4
@RoeeShenberg: skip(xrange(10000000), 1)irá usar at_end=0, então o parâmetro to deque()será islice(it, 0), que consumirá apenas zero elementos de it. Isso não vai ocupar muita memória.
Sven Marnach
8
for item in do_not_use_list_as_a_name[1:-1]:
    #...do whatever
KurzedMetal
fonte
3
Não use listcomo um nome de variável
Abhijit
o OP só quer pular o primeiro elemento. por que: -1?
precisa saber é o seguinte
6
Na verdade, não é reservado ; o nome listpode ser ligado novamente. É por isso que você não deve usá-lo , e não pode .
JSCs
@ luke14free, a pergunta diz pular o primeiro elemento, mas seu comentário de código implica que ele realmente quer pular o primeiro e o último.
amigos estão dizendo sobre jose carlos
@ luke14free isso é o que o título diz, não o que ele digitou dentro do código: "saltar se primeiro ou o último"
KurzedMetal
3

Baseado na resposta de @SvenMarnach, mas um pouco mais simples e sem usar o 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]

Observe também que, com base no meu timeitresultado, isso é marginalmente mais rápido que a solução 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
fonte
Ao usar tee(), você ainda está criando uma lista inteira na memória para o gerador, certo? (your it1)
Jabberwockey
3

Exemplo:

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

No índice python, inicie em 0, podemos usar o operador slicing para fazer manipulações na iteração.

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

Bem, para começar, sua sintaxe não é realmente Python.

As iterações no Python estão sobre o conteúdo dos contêineres (bem, tecnicamente sobre os iteradores), com uma sintaxe for item in container. Nesse caso, o contêiner é a carslista, mas você deseja pular o primeiro e o último elementos, o que significa cars[1:-1](as listas python são baseadas em zero, os números negativos são contados a partir do final e :estão cortando a sintaxe.

Então você quer

for c in cars[1:-1]:
    do something with c
Andrew Jaffe
fonte
4
Isso não funcionará com um iterável (por exemplo, um gerador), apenas com uma sequência.
Roee Shenberg 04/12/12
2

Um 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
Banana
fonte
2

Aqui está a minha escolha preferida. Não requer muito acréscimo ao loop e não usa nada além de ferramentas internas.

Vá de:

for item in my_items:
  do_something(item)

para:

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

Se carsé uma sequência, você pode simplesmente fazer

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

O more_itertoolsprojeto se estende itertools.islicepara lidar com índices negativos.

Exemplo

import more_itertools as mit

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

Portanto, você pode aplicá-lo de forma elegante a elementos de fatia entre o primeiro e o último itens de um iterável:

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

Eu faço assim, mesmo que pareça um hack, funciona sempre:

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
fonte