Gostaria de saber a melhor maneira (mais compacta e "pitônica") de fazer um tratamento especial para o último elemento em um loop for. Há um pedaço de código que deve ser chamado apenas entre os elementos, sendo suprimido no último.
Aqui está como eu faço atualmente:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
Existe alguma maneira melhor?
Nota: Eu não quero fazer isso com hacks, como usar reduce
.;)
Respostas:
Na maioria das vezes, é mais fácil (e mais barato) tornar a primeira iteração o caso especial, em vez da última:
Isso funcionará para qualquer iterável, mesmo para aqueles que não possuem
len()
:Além disso, não acho que exista uma solução geralmente superior, pois depende do que você está tentando fazer. Por exemplo, se você estiver construindo uma string a partir de uma lista, é naturalmente melhor usar do
str.join()
que usar umfor
loop "com caso especial".Usando o mesmo princípio, mas mais compacto:
Parece familiar, não é? :)
Para o @ofko e outros que realmente precisam descobrir se o valor atual de um iterável sem
len()
é o último, você precisará olhar para o futuro:Então você pode usá-lo assim:
fonte
if
que poderia ser evitado se o loop fosse dividido em dois loops. No entanto, isso é relevante apenas ao iterar uma enorme lista de dados.next()
. Exploro então que um iterador é iterável por si só, para que eu possa usá-lo nofor
loop até a exaustão, iteração do segundo ao último valor. Durante isso, mantenho o valor atual que recuperei do iterador localmente eyield
o último. Dessa forma, sei que há mais um valor por vir. Após o loop for, relatei todos os valores, exceto o último.Embora essa pergunta seja bastante antiga, eu vim aqui pelo google e achei uma maneira bastante simples: fatiar a lista. Digamos que você queira colocar um '&' entre todas as entradas da lista.
Isso retorna '1 e 2 e 3'.
fonte
len(l)=1000000
, neste exemplo, o programa for executado por um tempo.append
é recomendado afaik.l=[1,2,3]; l.append(4);
O 'código entre' é um exemplo do padrão Head-Tail .
Você tem um item, que é seguido por uma sequência de pares (entre itens). Você também pode ver isso como uma sequência de (item, entre) pares seguidos por um item. Geralmente é mais simples considerar o primeiro elemento como especial e todos os outros como o caso "padrão".
Além disso, para evitar a repetição de código, você deve fornecer uma função ou outro objeto para conter o código que não deseja repetir. A incorporação de uma instrução if em um loop que é sempre falsa, exceto que uma vez é meio boba.
Isso é mais confiável, porque é um pouco mais fácil de provar. Ele não cria uma estrutura de dados extra (ou seja, uma cópia de uma lista) e não requer muita execução desperdiçada de uma condição if que é sempre falsa, exceto uma vez.
fonte
if
instruções, para que o argumento "execução desperdiçada" não seja válido.if
s”. Obviamente você está apenas se referindo à "limpeza de código"?if
declaração é realmente considerado mais limpo pela comunidade Python?Se você está simplesmente querendo modificar o último elemento
data_list
, pode simplesmente usar a notação:No entanto, parece que você está fazendo mais do que isso. Não há nada realmente errado no seu caminho. Eu até dei uma rápida olhada em algum código do Django para suas tags de modelo e eles fazem basicamente o que você está fazendo.
fonte
if data != datalist[-1]:
e manter todo o resto igual seria a melhor maneira de codificar isso na minha opinião.se os itens forem exclusivos:
outras opções:
fonte
Isso é semelhante à abordagem do Ants Aasma, mas sem o uso do módulo itertools. Também é um iterador atrasado que antecipa um único elemento no fluxo do iterador:
fonte
Você pode usar uma janela deslizante sobre os dados de entrada para obter uma espiada no próximo valor e usar um sentinela para detectar o último valor. Isso funciona em qualquer iterável, portanto você não precisa saber o tamanho de antemão. A implementação em pares é das receitas do itertools .
fonte
Não há possibilidade de iterar sobre tudo, exceto o último elemento, e tratar o último fora do loop? Afinal, um loop é criado para fazer algo semelhante a todos os elementos em que você faz o loop; se um elemento precisa de algo especial, não deve estar no loop.
(veja também esta pergunta: o último elemento em um loop merece um tratamento separado )
EDIT: como a pergunta é mais sobre o "intermediário", o primeiro elemento é o especial por não ter predecessor ou o último elemento é especial por não ter sucessor.
fonte
Eu gosto da abordagem do @ ethan-t, mas
while True
é perigoso do meu ponto de vista.Aqui,
data_list
é para que o último elemento seja igual em valor ao primeiro da lista. L pode ser trocado,data_list
mas, neste caso, resulta vazio após o loop.while True
também é possível usar se você verificar se a lista não está vazia antes do processamento ou se a verificação não é necessária (ai!).A parte boa é que é rápido. O ruim - é destrutível (
data_list
fica vazio).Solução mais intuitiva:
Ah, sim, você já propôs!
fonte
Não há nada de errado com o seu caminho, a menos que você tenha 100.000 loops e queira salvar 100.000 instruções "se". Nesse caso, você pode seguir esse caminho:
Saídas:
Mas realmente, no seu caso, sinto que é um exagero.
De qualquer forma, você provavelmente terá mais sorte com o fatiamento:
ou apenas :
Eventualmente, uma maneira do KISS de fazer coisas para você, e que funcionaria com qualquer iterável, incluindo aqueles sem
__len__
:Ouputs:
Se parece que eu faria dessa maneira, parece simples para mim.
fonte
item
vez de recalculá-lo usandolist[-1]
. Mas, no entanto: eu não acho que isso é o que o OP estava pedindo, era?iterable.__iter__()
- por favor, não chame__
funções diretamente. Deveria seriter(iterable)
.Use o fatiamento e
is
para verificar o último elemento:Advertência : isso só funciona se todos os elementos da lista forem realmente diferentes (com locais diferentes na memória). Sob o capô, o Python pode detectar elementos iguais e reutilizar os mesmos objetos para eles. Por exemplo, para cadeias de caracteres do mesmo valor e números inteiros comuns.
fonte
se você está lendo a lista, para mim também funcionou:
fonte
O Google me levou a essa pergunta antiga e acho que poderia adicionar uma abordagem diferente para esse problema.
A maioria das respostas aqui trataria de um tratamento adequado de um controle de loop for, conforme solicitado, mas se a data_list for destrutível, sugiro que você apareça os itens da lista até terminar com uma lista vazia:
você pode até usar len (element_list) se não precisar fazer nada com o último elemento. Acho essa solução mais elegante do que lidar com next ().
fonte
Para mim, a maneira mais simples e pitônica de lidar com um caso especial no final de uma lista é:
Obviamente, isso também pode ser usado para tratar o primeiro elemento de uma maneira especial.
fonte
Em vez de contar, você também pode fazer uma contagem regressiva:
fonte
Atrasar o tratamento especial do último item até depois do loop.
fonte
Pode haver várias maneiras. fatiar será mais rápido. Adicionando mais um que usa o método .index ():
fonte
Assumindo a entrada como um iterador, aqui está uma maneira de usar tee e izip do itertools:
Demo:
fonte
A solução mais simples que me vem à cabeça é:
Portanto, sempre observamos um item adiando a iteração de processamento. Para pular algo durante a primeira iteração, simplesmente pego o erro.
É claro que você precisa pensar um pouco, a fim de
NameError
aumentar quando quiser.Mantenha também o `` counstruct
Isso depende que o nome novo não foi definido anteriormente. Se você é paranóico, pode garantir que
new
isso não exista usando:Como alternativa, é claro que você também pode usar uma instrução if (
if notfirst: print(new) else: notfirst = True
). Mas, tanto quanto eu sei, a sobrecarga é maior.então, espero que a sobrecarga seja inelegível.
fonte
Conte os itens uma vez e acompanhe o número de itens restantes:
Dessa forma, você avalia apenas o comprimento da lista uma vez. Muitas das soluções nesta página parecem assumir que o tamanho não está disponível antecipadamente, mas isso não faz parte da sua pergunta. Se você tem o comprimento, use-o.
fonte
Uma solução simples que vem à mente seria:
Uma segunda solução igualmente simples pode ser alcançada usando um contador:
fonte