Pergunta

Estou interagindo sobre uma lista de tuplas em Python, e estou tentando removê-los se cumprirem determinados critérios.

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

O que devo usar no lugar do code_to_remove_tup? Eu não consigo descobrir como remover o item desta forma.

Foi útil?

Solução

Você pode usar uma compreensão de lista para criar uma nova lista contendo apenas os elementos que você não deseja remover:

somelist = [x for x in somelist if not determine(x)]

Ou, atribuindo ao somelist[:] fatia, você pode transformar a lista existente para conter apenas os itens que você deseja:

somelist[:] = [x for x in somelist if not determine(x)]

Esta abordagem pode ser útil se existem outras referências a somelist que necessidade de reflectir as alterações.

Em vez de uma compreensão, você também pode usar itertools. Em Python 2:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

Ou em Python 3:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)

Outras dicas

As respostas sugerem compreensões lista são quase correta - exceto que eles constroem uma nova lista e, em seguida, dar-lhe o mesmo nome da lista antiga como, eles não modificar a lista de idade no lugar. Isso é diferente do que você estaria fazendo por remoção seletiva, como em @ de Lennart sugestão - é mais rápido, mas se o seu lista é acessado através de várias referências ao fato de que você está apenas recolocar uma das referências e não alterar o objeto de lista em si pode levar a sutis, erros desastrosos.

Felizmente, é extremamente fácil de obter tanto a velocidade de compreensões lista e a semântica necessários de alteração no local - apenas código:

somelist[:] = [tup for tup in somelist if determine(tup)]

Note a diferença sutil com outras respostas: este não é atribuir a um barename - é atribuir a uma fatia lista que só acontece de ser a lista inteira, substituindo assim a lista conteúdo dentro da mesma lista de objetos Python , ao invés de apenas recolocar uma referência (de anterior objeto de lista para o novo objeto de lista) como as outras respostas.

Você precisa ter uma cópia da lista e iterar sobre ele em primeiro lugar, ou a iteração irá falhar com o que pode ser resultados inesperados.

Por exemplo (depende de que tipo de lista):

for tup in somelist[:]:
    etc....

Um exemplo:

>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]
for i in range(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

Você precisa ir para trás caso contrário, é um pouco como serrar o galho de árvore que você está sentado em: -)

usuários Python 2: substituir range por xrange para evitar a criação de uma lista codificada

Seu melhor abordagem para tal exemplo seria um compreensão da lista

somelist = [tup for tup in somelist if determine(tup)]

Nos casos em que você está fazendo algo mais complexo do que chamar uma função determine, eu prefiro a construção de uma nova lista e simplesmente anexar a ele como eu ir. Por exemplo

newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

Copiar a lista usando remove pode tornar seu código olhar um pouco mais limpa, como descrito em uma das respostas abaixo. Você definitivamente não deve fazer isso por muito grandes listas, uma vez que este envolve primeiro copiar a lista inteira, e também executar uma operação O(n) remove para cada elemento a ser removido, tornando este algoritmo um O(n^2).

for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)

Python Oficial 2 tutorial 4.2. "Para Statements"

https://docs.python.org/2/tutorial /controlflow.html#for-statements

Esta parte dos documentos deixa claro que:

  • você precisa para fazer uma cópia da lista iterado para modificá-lo
  • Uma maneira de fazer isso é com a fatia de notação [:]

Se precisar modificar a sequência que você está interagindo sobre enquanto no interior do loop (por exemplo para duplicar itens selecionados), é recomendável que você primeiro fazer uma cópia. Iteração sobre uma seqüência não implicitamente fazer uma cópia. A notação fatia torna este especialmente conveniente:

>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

Python 2 documentação 7.3. "O comando for"

https://docs.python.org/2/reference/compound_stmts .html # para

Esta parte dos docs diz mais uma vez que você tem que fazer uma cópia, e dá um exemplo remoção real:

Nota: Não é uma subtileza quando a sequência está a ser modificado pela espira (isto somente pode ocorrer por sequências mutáveis, isto listas). Um contador interno é usado para manter o controle de qual item é usado seguinte, e este é incrementado a cada iteração. Quando este contador tiver atingido o comprimento da sequência do loop termina. Isto significa que se exclui o conjunto a corrente (ou um anterior) produto a partir da sequência, o próximo item será ignorado (desde que deixa o índice do item corrente que já foi tratada). Da mesma forma, se o conjunto insere um artigo na sequência antes do item corrente, a corrente de produto vai ser tratado novamente a próxima vez que o loop. Isso pode levar a bugs que podem ser evitados fazendo uma cópia temporária usando uma fatia de toda a sequência, por exemplo.,

for x in a[:]:
    if x < 0: a.remove(x)

No entanto, não concordo com esta implementação, desde .remove() tem para percorrer o lista inteira para encontrar o valor.

Em vez disso, quer:

Geralmente você só quer ir para a opção mais rápida .append() por padrão, a menos que a memória é uma grande preocupação.

Poderia Python fazer isso melhor?

Parece que este API Python particular poderia ser melhorado. Compare-o, por exemplo, com o seu homólogo Java ListIterator , o que torna claro que você não pode modificar uma lista ser iterado exceto com o iterador em si, e dá-lhe maneiras eficientes de fazer isso sem copiar a lista.

Talvez a lógica subjacente é que as listas Python são assumidos como matriz dinâmica apoiada, e, por conseguinte, qualquer tipo de remoção será tempo de qualquer maneira ineficiente, enquanto Java tem uma hierarquia de interface mais agradável com ambos ArrayList e LinkedList implementações de ListIterator.

Não parece ser um tipo de lista ligada explícita no stdlib Python ou: Python Linked Lista

Para aqueles que, como programação funcional:

somelist[:] = filter(lambda tup: not determine(tup), somelist)

ou

from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))

Pode ser inteligente para também acaba de criar uma nova lista, se o item da lista atual atende aos critérios desejados.

forma:

for item in originalList:
   if (item != badValue):
        newList.append(item)

e para evitar ter que re-código de todo o projeto com o novo nome listas:

originalList[:] = newList

Nota, a partir da documentação Python:

copy.copy (x) Retornar uma cópia superficial do x.

copy.deepcopy (x) Retornar uma cópia profunda x.

Eu precisava fazer isso com uma lista enorme, e duplicar a lista parecia caro, especialmente porque no meu caso o número de exclusões seriam poucos em comparação com os itens que permanecem. Tomei esta abordagem de baixo nível.

array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1

O que eu não sei é como eficiente um par de exclusões são comparados com a cópia de um grande lista. Por favor, comente se você tem alguma idéia.

Essa resposta foi originalmente escrito em resposta a uma questão que já foi marcado como duplicado: Remoção coordenadas da lista em python

Existem dois problemas em seu código:

1) Ao usar remove (), você tentar remover inteiros enquanto você precisa remover uma tupla.

2) O laço for irá ignorar itens em sua lista.

Vamos correr com o que acontece quando executamos o código:

>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)

O primeiro problema é que você está passando tanto 'a' e 'b' para remover (), mas remove () só aceita um único argumento. Então, como podemos obter remove () para funcionar corretamente com a sua lista? Precisamos descobrir o que cada elemento da sua lista é. Neste caso, cada um é uma tupla. Para ver isto, deixe o acesso do elemento um da lista (começa a indexar a 0):

>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>

Aha! Cada elemento da L1 é realmente uma tupla. Então é isso que nós precisamos de estar passando para remover (). Tuplas em python são muito fácil, eles estão simplesmente fez colocando valores entre parênteses. "A, b" não é uma tupla, mas "(a, b)" é uma tupla. Por isso, modificar o código e executá-lo novamente:

# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))

esse código é executado sem qualquer erro, mas vamos olhar para a lista ele gera:

L1 is now: [(1, 2), (5, 6), (1, -2)]

Por que é (1, -2) ainda em sua lista? Acontece modificar a lista enquanto estiver usando um loop para iterar sobre ele é uma idéia muito ruim, sem cuidados especiais. A razão que (1, -2) permanece na lista é que os locais de cada item na lista alterada entre iterações do loop for. Vamos olhar o que acontece se nós alimentamos o código acima uma lista mais longa:

L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

Como você pode inferir a partir desse resultado, cada vez que os avalia instrução condicional para verdadeiro e um item da lista é removido, a próxima iteração do loop irá ignorar a avaliação do próximo item na lista porque seus valores são agora localizado em diferentes índices.

A solução mais intuitiva é para copiar a lista, em seguida, iterar sobre a lista original e apenas modificar a cópia. Você pode tentar fazê-lo como este:

L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)

No entanto, a saída será idêntico ao anterior:

'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

Isto é porque quando criamos L2, python não chegou a criar um novo objeto. Em vez disso, apenas referenciada L2 para o mesmo objeto como L1. Podemos verificar isso com 'é' que é diferente de meramente "iguais" (==).

>>> L2=L1
>>> L1 is L2
True

Podemos fazer uma cópia usando copy.copy (). Em seguida, tudo funciona como esperado:

import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

Finalmente, há uma solução mais limpa do que ter de fazer uma cópia inteiramente nova de L1. A função invertida ():

L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

Infelizmente, não posso adequadamente descrever como invertida () funciona. Ele retorna um objeto 'listreverseiterator' quando uma lista é passado para ele. Para fins práticos, você pode pensar nisso como a criação de uma cópia invertida de seu argumento. Esta é a solução que eu recomendo.

Se você quiser fazer qualquer outra coisa durante a iteração, pode ser agradável para obter tanto o índice (que lhe garante ser capaz de fazer referência a ela, por exemplo, se você tem uma lista de dicts) e as reais conteúdo item da lista.

inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
for idx, i in enumerate(inlist):
    do some stuff with i['field1']
    if somecondition:
        xlist.append(idx)
for i in reversed(xlist): del inlist[i]

enumerate dá-lhe acesso ao item e o índice de uma só vez. reversed é para que os índices que você vai eliminar mais tarde não mudam em você.

Você pode querer usar filter() disponível como o built-in.

Para mais detalhes confira aqui

Você pode tentar a for-loop no sentido inverso então para some_list você vai fazer algo como:

list_len = len(some_list)
for i in range(list_len):
    reverse_i = list_len - 1 - i
    cur = some_list[reverse_i]

    # some logic with cur element

    if some_condition:
        some_list.pop(reverse_i)

Desta forma, o índice está alinhado e não sofre as atualizações da lista (independentemente se você pop cur elemento ou não).

Uma possível solução, útil se você não quer só remover algumas coisas, mas também fazer algo com todos os elementos em um único loop:

alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
    if x == 'bad':
        alist.pop(i)
        i -= 1
    # do something cool with x or just print x
    print(x)
    i += 1

A maioria das respostas aqui quero que você criar uma cópia da lista. Eu tive um caso de uso em que a lista foi bastante longo (110K itens) e foi mais inteligente para manter reduzir a lista em seu lugar.

Primeiro de tudo você precisa substituir loop foreach com while ,

i = 0
while i < len(somelist):
    if determine(somelist[i]):
         del somelist[i]
    else:
        i += 1

O valor da i não é alterado no bloco if porque você vai querer obter o valor do novo item do mesmo índice, uma vez que o item antigo é excluído.

Eu precisava fazer algo semelhante e no meu caso era o problema de memória - Eu precisava mesclar vários objetos de conjuntos de dados dentro de uma lista, depois de fazer algumas coisas com eles, como um novo objeto, e precisava se livrar de cada entrada I foi se fundindo para evitar a duplicação de todos eles e explodir memória. No meu caso ter os objetos em um dicionário em vez de uma lista funcionou bem:

`` `

k = range(5)
v = ['a','b','c','d','e']
d = {key:val for key,val in zip(k, v)}

print d
for i in range(5):
    print d[i]
    d.pop(i)
print d

`` `

TLDR:

Eu escrevi uma biblioteca que permite que você faça o seguinte:

from fluidIter import FluidIterable
fSomeList = FluidIterable(someList)  
for tup in fSomeList:
    if determine(tup):
        # remove 'tup' without "breaking" the iteration
        fSomeList.remove(tup)
        # tup has also been removed from 'someList'
        # as well as 'fSomeList'

É melhor usar um outro método, se possível, que não requer modificar o seu iterable enquanto Iterando sobre ele, mas para alguns algoritmos que pode não ser tão simples. E por isso, se tiver certeza de que você realmente deseja que o padrão de código descrito na pergunta original, é possível.

deve funcionar em todas as sequências mutáveis ??não apenas listas.


resposta completa:

Edit: O último exemplo de código nesta resposta dá um caso de uso para por que você pode, por vezes, deseja modificar uma lista no lugar, em vez de usar uma lista de compreensão. A primeira parte das respostas serve como tutorial de como um array pode ser modificado no lugar.

A solução surge na sequência esta resposta (para uma questão relacionada) de senderle. Que explica como o índice da matriz é atualizado durante a iteração através de uma lista que tenha sido modificado. A solução abaixo é concebido para controlar correctamente o índice de matriz, mesmo se a lista é modificada.

Fazer download fluidIter.py de https://github.com/alanbacon/FluidIterator aqui , é apenas um único arquivo assim não há necessidade de instalar git. Não há instalador assim que você vai precisar para se certificar de que o arquivo está no caminho python seu self. O código foi escrito para python 3 e não foi testado em python 2.

from fluidIter import FluidIterable
l = [0,1,2,3,4,5,6,7,8]  
fluidL = FluidIterable(l)                       
for i in fluidL:
    print('initial state of list on this iteration: ' + str(fluidL)) 
    print('current iteration value: ' + str(i))
    print('popped value: ' + str(fluidL.pop(2)))
    print(' ')

print('Final List Value: ' + str(l))

Isto produzirá o seguinte resultado:

initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
current iteration value: 0
popped value: 2

initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
current iteration value: 1
popped value: 3

initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
current iteration value: 4
popped value: 4

initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
current iteration value: 5
popped value: 5

initial state of list on this iteration: [0, 1, 6, 7, 8]
current iteration value: 6
popped value: 6

initial state of list on this iteration: [0, 1, 7, 8]
current iteration value: 7
popped value: 7

initial state of list on this iteration: [0, 1, 8]
current iteration value: 8
popped value: 8

Final List Value: [0, 1]

Acima temos utilizado o método pop sobre o objeto da lista de fluido. Outros métodos iteráveis ??comuns também são implementadas como del fluidL[i], .remove, .insert, .append, .extend. A lista também pode ser modificada usando fatias (métodos sort e reverse não são implementados).

A única condição é que você só deve modificar a lista no lugar, se em algum fluidL ponto ou l foram realocados para um objeto lista diferente o código não iria funcionar. O objeto fluidL original seria ainda ser usado pelo laço for, mas se tornaria fora do escopo para nós modificar.

i.

fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK

Se queremos acessar o valor do índice atual da lista, não podemos usar enumerar, pois isso só contagem de quantas vezes o loop foi executado. Em vez disso, vamos usar o objeto iterador diretamente.

fluidArr = FluidIterable([0,1,2,3])
# get iterator first so can query the current index
fluidArrIter = fluidArr.__iter__()
for i, v in enumerate(fluidArrIter):
    print('enum: ', i)
    print('current val: ', v)
    print('current ind: ', fluidArrIter.currentIndex)
    print(fluidArr)
    fluidArr.insert(0,'a')
    print(' ')

print('Final List Value: ' + str(fluidArr))

A saída será o seguinte:

enum:  0
current val:  0
current ind:  0
[0, 1, 2, 3]

enum:  1
current val:  1
current ind:  2
['a', 0, 1, 2, 3]

enum:  2
current val:  2
current ind:  4
['a', 'a', 0, 1, 2, 3]

enum:  3
current val:  3
current ind:  6
['a', 'a', 'a', 0, 1, 2, 3]

Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]

A classe FluidIterable apenas fornece um wrapper para o objeto lista original. O objeto original pode ser acessado como uma propriedade do objeto fluido assim:

originalList = fluidArr.fixedIterable

Mais exemplos / testes podem ser encontrados na secção if __name__ is "__main__": na parte inferior da fluidIter.py. Estes são vale a pena olhar, porque eles explicam o que acontece em várias situações. Tais como: Substituir um grande seções da lista usando uma fatia. Ou usando (e modificando) o mesmo iteráveis ??em nested loops.

Como eu disse para começar: esta é uma solução complicada que irá prejudicar a legibilidade do seu código e torná-lo mais difícil de depurar. Portanto outras soluções, como as compreensões lista mencionada no responder deve ser considerado em primeiro lugar. Dito isto, eu descobri momentos em que esta classe tem sido útil para mim e tem sido mais fácil de usar do que manter o controle dos índices de elementos que precisam de exclusão.


Edit: Como mencionado nos comentários, esta resposta não é realmente um problema para que esta abordagem fornece uma solução. Vou tentar endereço que aqui:

Lista compreensões fornecem uma maneira de gerar uma nova lista, mas estas abordagens tendem a olhar para cada elemento em Isolação, em vez do estado atual da lista como um todo.

i.

newList = [i for i in oldList if testFunc(i)]

Mas, e se o resultado da testFunc depende dos elementos que foram adicionados ao já newList? Ou os elementos ainda em oldList que pode ser adicionado a seguir? Há ainda pode ser uma maneira de usar uma compreensão da lista, mas ele vai começar a perder a sua elegância, e para mim ele se sente mais fácil de modificar uma lista no lugar.

O código a seguir é um exemplo de um algoritmo que sofre com o problema acima. O algoritmo irá reduzir a lista para que nenhum elemento é um múltiplo de qualquer outro elemento.

randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
fRandInts = FluidIterable(randInts)
fRandIntsIter = fRandInts.__iter__()
# for each value in the list (outer loop)
# test against every other value in the list (inner loop)
for i in fRandIntsIter:
    print(' ')
    print('outer val: ', i)
    innerIntsIter = fRandInts.__iter__()
    for j in innerIntsIter:
        innerIndex = innerIntsIter.currentIndex
        # skip the element that the outloop is currently on
        # because we don't want to test a value against itself
        if not innerIndex == fRandIntsIter.currentIndex:
            # if the test element, j, is a multiple 
            # of the reference element, i, then remove 'j'
            if j%i == 0:
                print('remove val: ', j)
                # remove element in place, without breaking the
                # iteration of either loop
                del fRandInts[innerIndex]
            # end if multiple, then remove
        # end if not the same value as outer loop
    # end inner loop
# end outerloop

print('')
print('final list: ', randInts)

A saída e a lista reduzida final são mostrados abaixo

outer val:  70

outer val:  20
remove val:  80

outer val:  61

outer val:  54

outer val:  18
remove val:  54
remove val:  18

outer val:  7
remove val:  70

outer val:  55

outer val:  9
remove val:  18

final list:  [20, 61, 7, 55, 9]

As outras respostas estão corretas, que geralmente é uma má idéia para apagar a partir de uma lista que você está iteração. Reverter a iteração evita as armadilhas, mas é muito mais difícil de seguir código que faz isso, então geralmente é melhor usar uma compreensão lista ou filter.

Há, no entanto, um caso em que ele é seguro para remover elementos de uma seqüência que você é a iteração: se você está removendo apenas um item enquanto estiver a iteração. Isto pode ser conseguido usando um return ou um break. Por exemplo:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

Este é muitas vezes mais fácil de entender do que uma compreensão lista quando você está fazendo algumas operações com efeitos colaterais sobre o primeiro item de uma lista que reúne alguma condição e, em seguida, remover o item da lista imediatamente depois.

O método mais eficaz é compreensão da lista, muitas pessoas mostram seu caso, é claro, também é uma boa maneira de obter uma iterator através filter.

Filter recebe uma função e uma sequência. Filter aplica a função passada para cada elemento, por sua vez, e então decide se deseja manter ou descartar o elemento dependendo se o valor da função de retorno é True ou False.

Há um exemplo (obter as probabilidades na tupla):

list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
# result: [1, 5, 9, 15]

Atenção: Você também não pode lidar com iteradores. Iterators são, por vezes melhor do que seqüências.

Não consigo pensar em três abordagens para resolver seu problema. Como exemplo, vou criar uma lista aleatória de tuplas somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)]. A condição que eu escolho é sum of elements of a tuple = 15. Na lista final teremos apenas aquelas tuplas cuja soma não é igual a 15.

O que eu escolhi é um exemplo escolhido aleatoriamente. Sinta-se livre para mudar lista de tuplas e condição que escolhi.

Método 1.> Use o quadro que você tinha sugerido (onde um preenchimentos em um código dentro de um loop). Eu uso um pequeno código com del para excluir uma tupla que satisfaz a referida condição. No entanto, este método vai perder um tuplo (que satisfaz a referida condição) se dois tuplos consecutivamente colocados satisfazer a condição dada.

for tup in somelist:
    if ( sum(tup)==15 ): 
        del somelist[somelist.index(tup)]

print somelist
>>> [(1, 2, 3), (3, 6, 6), (7, 8, 9), (10, 11, 12)]

Método 2.> Construir uma nova lista que contém elementos (linhas), onde a condição dada não for cumprida (esta é a mesma coisa como a remoção de elementos da lista onde a condição dada é Met). Segue-se o código para isso:

newlist1 = [somelist[tup] for tup in range(len(somelist)) if(sum(somelist[tup])!=15)]

print newlist1
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

Método 3.> Localizar índices onde a condição dada é Met, e, em seguida, utilizar os elementos de remoção (tuplos) correspondentes a esses índices. Segue-se o código para isso.

indices = [i for i in range(len(somelist)) if(sum(somelist[i])==15)]
newlist2 = [tup for j, tup in enumerate(somelist) if j not in indices]

print newlist2
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

método 1 e método 2 são mais rápidos do que o método 3 . Method2 e method3 são mais eficientes que method1. I preferem method2 . Para o exemplo acima, time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7

para ciclo irá ser iterada através índice ..

considerar que você tem uma lista,

[5, 7, 13, 29, 65, 91]

Você tem usando variável de lista denominada lis. e você usar mesmo para remover ..

a variável

lis = [5, 7, 13, 29, 35, 65, 91]
       0  1   2   3   4   5   6

durante a 5ª iteração,

o número 35 não era um primo para que removeu a partir de uma lista.

lis.remove(y)

e, em seguida, valor seguinte (65) passar para índice anterior.

lis = [5, 7, 13, 29, 65, 91]
       0  1   2   3   4   5

para 4ª iteração ponteiro feito se mudou para quinta ..

é por isso que o seu ciclo does not cover 65 desde o seu mudou para índice anterior.

para que você não deve lista de referência em outra variável que ainda referência original em vez de cópia.

ite = lis #dont do it will reference instead copy

para fazer cópia da lista usando list[::]

Agora você vai dar,

[5, 7, 13, 29]

O problema é que você removeu um valor a partir de uma lista durante a iteração, em seguida, o seu índice de lista entrará em colapso.

para que você pode tentar compreensão vez.

que suporta todo o iterable como, lista, tupla, dict, corda etc

Para qualquer coisa que tenha o potencial de ser muito grande, eu uso o seguinte.

import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

Isso deve ser significativamente mais rápido do que qualquer outra coisa.

Em algumas situações, onde você está fazendo mais do que simplesmente filtrar uma lista um item de cada vez, você quer que seu iteração para a mudança, enquanto a iteração.

Aqui está um exemplo onde copiar a lista de antemão é incorreta, inverta iteração é impossível e uma compreensão da lista também não é uma opção.

""" Sieve of Eratosthenes """

def generate_primes(n):
    """ Generates all primes less than n. """
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p

Se você vai usar a nova lista mais tarde, você pode simplesmente definir o elem para Nenhum, e depois julgá-lo no circuito depois, como este

for i in li:
    i = None

for elem in li:
    if elem is None:
        continue

Desta forma, você dont't precisa copiar a lista e é mais fácil de entender.

uppose uma lista de número e você deseja remover todos sem que são divisível por 3,

list_number =[i for i in range(100)]

usando list comprehension, isso vai careate uma nova lista e criar um novo espaço de memória

new_list =[i for i in list_number if i%3!=0]

usando a função lambda filter, isso vai criar resultante nova lista e consumir espaço memeory

new_list = list(filter(lambda x:x%3!=0, list_number))

sem consumir espaço de memória para nova lista e modificar lista existente

for index, value in enumerate(list_number):
    if list_number[index]%3==0:
        list_number.remove(value)

Imediatamente você deseja criar uma cópia da lista, assim você pode ter isso como uma referência quando se está a iteração através de e apagar tuplas nessa lista que atendem a determinados critérios.

Em seguida, ele depende de que tipo de lista que você deseja para a saída mesmo que seja uma lista de tuplas removidos ou uma lista de tuplas que não são removidos.

Como David apontou, eu recomendo compreensão de lista para manter os elementos que você não deseja remover.

somelist = [x for x in somelist if not determine(x)]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top