Esiste un modo semplice per eliminare un elemento elenco in base al valore?


942
a = [1, 2, 3, 4]
b = a.index(6)

del a[b]
print(a)

Quanto sopra mostra il seguente errore:

Traceback (most recent call last):
  File "D:\zjm_code\a.py", line 6, in <module>
    b = a.index(6)
ValueError: list.index(x): x not in list

Quindi devo fare questo:

a = [1, 2, 3, 4]

try:
    b = a.index(6)
    del a[b]
except:
    pass

print(a)

Ma non esiste un modo più semplice per farlo?


14
Calcoli l'indice di 6 nella tua lista. Ma 6 non è nella tua lista ... quindi cosa dovrebbe succedere? :)
Johannes Charra,

5
questo non ha nulla a che fare con l'eliminazione di un valore in un elenco, poiché il codice non raggiunge l'istruzione del. Forse dovresti ridisegnarlo "come posso ottenere l'indice di un valore che non è in una lista. Risposta ovvia - non puoi.
Dave Kirby

57
@Dave Bene, non proprio. Vuole eliminare un elemento dall'elenco indipendentemente dal fatto che esista o meno, non ottenere l'indice per un elemento inesistente. La domanda è ben fatta.
ibz,

Accanto al punto, ma una nuda exceptè una cattiva pratica . Utilizzare except Exceptioncome minimo.
wjandrea,

Risposte:


1565

Per rimuovere la prima occorrenza di un elemento in un elenco, utilizzare semplicemente list.remove:

>>> a = ['a', 'b', 'c', 'd']
>>> a.remove('b')
>>> print(a)
['a', 'c', 'd']

Ricorda che non rimuove tutte le occorrenze del tuo elemento. Usa una comprensione dell'elenco per quello.

>>> a = [10, 20, 30, 40, 20, 30, 40, 20, 70, 20]
>>> a = [x for x in a if x != 20]
>>> print(a)
[10, 30, 40, 30, 40, 70]

144
Non riesce se l'elemento non è nell'elenco. :)
ibz,

21
La comprensione dell'elenco @ibz non fallisce anche se l'elemento non è nell'elenco, vero?
Isacco

76
Per chiarire chi scrematura, "fallisce", nel senso che genera un'eccezione ValueError.
Casey Falk,

10
La comprensione dell'elenco modifica il riferimento dell'elenco, quindi se esiste una copia del riferimento da qualche parte, la rimozione non seguirà.
Sebastien,

Qual è la complessità di removeè O (n)?
Rasmi Ranjan Nayak,

184

Di solito Python genererà un'eccezione se gli dici di fare qualcosa che non può, quindi dovrai farlo:

if c in a:
    a.remove(c)

o:

try:
    a.remove(c)
except ValueError:
    pass

Un'eccezione non è necessariamente una cosa negativa purché sia ​​quella che ti aspetti e gestisci correttamente.


9
Prevenire è meglio che curare. Se è possibile verificare prima le condizioni eccezionali (esempio a), è necessario.
Gusdor,

82
Sebbene ciò sia vero in altre lingue, in Python è "più facile chiedere perdono che permesso". docs.python.org/2/glossary.html#term-eafp
Dave Webb

6
@Gusdor: se l'elenco è condiviso tra thread, a.remove(c)potrebbe comunque non riuscire nonostante il if c in acontrollo ( apotrebbe essere modificato in un altro thread dopo il c in acontrollo ma prima della a.remove(c)chiamata). try/exceptoppure i blocchi potrebbero essere utilizzati per evitare le condizioni di gara.
jfs,

7
@JFSebastian se un elenco è condiviso tra thread e non stai applicando sezioni critiche, allora hai problemi più grandi.
Gusdor,

4
@Gusdor, l'idioma di Pythonique è provare senza controllare e cogliere l'eccezione se si verifica. È più efficiente (solo una ricerca anziché due), anche se un po 'più brutto
Jeet

80

Tu puoi fare

a=[1,2,3,4]
if 6 in a:
    a.remove(6)

ma sopra è necessario cercare 6 nell'elenco 2 volte, quindi prova tranne che sarebbe più veloce

try:
    a.remove(6)
except:
    pass

55

Prendere in considerazione:

a = [1,2,2,3,4,5]

Per eliminare tutte le occorrenze, è possibile utilizzare la funzione filtro in Python. Ad esempio, sembrerebbe:

a = list(filter(lambda x: x!= 2, a))

Quindi, manterrebbe tutti gli elementi di a != 2.

Per estrarre solo uno degli oggetti usa

a.remove(2)

Perché ti avvolgi filter()in un altro list()? Secondo il manuale, restituisce già un elenco.
Olaf Dietsche,

8
@OlafDietsche In Python 3.x, restituisce un oggetto filtro (in 2.x, restituisce un elenco), quindi devo lanciare "a" in un elenco affinché abbia funzionalità.
mathwizurd,

17

Ecco come farlo sul posto (senza comprensione dell'elenco):

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]

Molto intelligente, mi piace molto, purtroppo sembra inefficiente come la risposta più popolare. La soluzione di gil è in realtà molto più veloce per le liste giganti con solo poche occorrenze del valore che si desidera rimuovere.
Larold,

1
@Larold Il modo più veloce sarebbe una domanda separata. I miei soldi sono sulla comprensione della lista nel caso generale. Questa soluzione dovrebbe funzionare davvero bene se il valore è frequente nell'elenco di input e la comprensione dell'elenco non viene utilizzata. Prova i dati Pypy e numpy in Cython. [La risposta di @ Gill è O(n*n)inutilmente (confronta 1e6 e 1e12 - non vuoi rischiare quest'ultima). while 1: L.remove(value)e return on ValueErrorpotrebbe funzionare bene con alcuni values o piccoli elenchi in CPython.
jfs

13

Se sai quale valore eliminare, ecco un modo semplice (il più semplice possibile, comunque):

a = [0, 1, 1, 0, 1, 2, 1, 3, 1, 4]
while a.count(1) > 0:
    a.remove(1)

Otterrai [0, 0, 2, 3, 4]


4
Perché non usare while 1 in a:come struttura ad anello?
TerminalDilettante,

12
Questo è O(n^2)dove sarebbe una comprensione O(n).
Fisico pazzo,

1
Ovviamente @MadPhysicist ha ragione, e la versione di TerminalDilettante è molto più pitonica, anche se non ci importa delle prestazioni. Nel 2013 ho iniziato a studiare Python e oggi mi vergogno abbastanza spesso di ciò che ho scritto allora.
Gil

11

Un'altra possibilità è quella di utilizzare un set anziché un elenco, se un set è applicabile nella propria applicazione.

IE se i tuoi dati non sono ordinati e non hanno duplicati, quindi

my_set=set([3,4,2])
my_set.discard(1)

è privo di errori.

Spesso un elenco è solo un comodo contenitore per gli articoli che sono effettivamente non ordinati. Ci sono domande che chiedono come rimuovere tutte le occorrenze di un elemento da un elenco. Se in primo luogo non vuoi duplicati, ancora una volta è utile un set.

my_set.add(3)

non cambia my_set dall'alto.


10

Come affermato da numerose altre risposte, list.remove()funzionerà, ma lancia un ValueErrorse l'elemento non era nell'elenco. Con python 3.4+, esiste un approccio interessante alla gestione di questo, usando il gestore di soppressione :

from contextlib import suppress
with suppress(ValueError):
    a.remove('b')

8

Trovare un valore in un elenco e quindi eliminare quell'indice (se esiste) è più facile semplicemente usando il metodo di rimozione dell'elenco:

>>> a = [1, 2, 3, 4]
>>> try:
...   a.remove(6)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 3, 4]
>>> try:
...   a.remove(3)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 4]

Se lo fai spesso, puoi avvolgerlo in una funzione:

def remove_if_exists(L, value):
  try:
    L.remove(value)
  except ValueError:
    pass

8

Questo esempio è veloce e cancellerà tutte le istanze di un valore dall'elenco:

a = [1,2,3,1,2,3,4]
while True:
    try:
        a.remove(3)
    except:
        break
print a
>>> [1, 2, 1, 2, 4]

2
se si fa questo si dovrebbe davvero solo breaksu except ValueError.
Anthon,

8

In una riga:

a.remove('b') if 'b' in a else None

a volte è utile.

Ancora più semplice:

if 'b' in a: a.remove('b')

7

Se i tuoi elementi sono distinti, allora farà una semplice differenza di serie.

c = [1,2,3,4,'x',8,6,7,'x',9,'x']
z = list(set(c) - set(['x']))
print z
[1, 2, 3, 4, 6, 7, 8, 9]

2
Se i tuoi elementi sono distinti e non ti interessa l'ordine .
Tom Zych,

2

Possiamo anche usare .pop:

>>> lst = [23,34,54,45]
>>> remove_element = 23
>>> if remove_element in lst:
...     lst.pop(lst.index(remove_element))
... 
23
>>> lst
[34, 54, 45]
>>> 

2

Sovrascrivi l'elenco indicizzando tutto tranne gli elementi che desideri rimuovere

>>> s = [5,4,3,2,1]
>>> s[0:2] + s[3:]
[5, 4, 2, 1]

2

Con un ciclo for e una condizione:

def cleaner(seq, value):    
    temp = []                      
    for number in seq:
        if number != value:
            temp.append(number)
    return temp

E se vuoi rimuoverne alcuni, ma non tutti:

def cleaner(seq, value, occ):
    temp = []
    for number in seq:
        if number == value and occ:
            occ -= 1
            continue
        else:
            temp.append(number)
    return temp

1
 list1=[1,2,3,3,4,5,6,1,3,4,5]
 n=int(input('enter  number'))
 while n in list1:
    list1.remove(n)
 print(list1)

È senza usare la funzione filtro
Ravikiran D

1

Ad esempio, vogliamo rimuovere tutti gli 1 da x. Ecco come lo farei:

x = [1, 2, 3, 1, 2, 3]

Ora, questo è un uso pratico del mio metodo:

def Function(List, Unwanted):
    [List.remove(Unwanted) for Item in range(List.count(Unwanted))]
    return List
x = Function(x, 1)
print(x)

E questo è il mio metodo in una sola riga:

[x.remove(1) for Item in range(x.count(1))]
print(x)

Entrambi producono questo come output:

[2, 3, 2, 3, 2, 3]

Spero che sia di aiuto. PS, tieni presente che questo è stato scritto nella versione 3.6.2, quindi potrebbe essere necessario modificarlo per le versioni precedenti.


1

Forse le tue soluzioni funzionano con ints, ma non funziona con me con dizionari.

In una mano, remove () non ha funzionato per me. Ma forse funziona con i tipi di base. Immagino che il codice seguente sia anche il modo di rimuovere elementi dall'elenco degli oggetti.

D'altra parte, 'del' non ha funzionato correttamente neanche. Nel mio caso, usando python 3.6: quando provo a cancellare un elemento da una lista in un comando 'for' con il comando 'del', python cambia l'indice nel processo e bucle si ferma prematuramente prima del tempo. Funziona solo se elimini elemento per elemento in ordine inverso . In questo modo non cambi l'indice dell'array degli elementi in sospeso quando lo attraversi

Quindi, ho usato:

c = len(list)-1
for element in (reversed(list)):
    if condition(element):
        del list[c]
    c -= 1
print(list)

dove 'list' è come [{'key1': value1 '}, {' key2 ': value2}, {' key3 ': value3}, ...]

Inoltre puoi fare più pythonic usando enumerate:

for i, element in enumerate(reversed(list)):
    if condition(element):
        del list[(i+1)*-1]
print(list)

0
arr = [1, 1, 3, 4, 5, 2, 4, 3]

# to remove first occurence of that element, suppose 3 in this example
arr.remove(3)

# to remove all occurences of that element, again suppose 3
# use something called list comprehension
new_arr = [element for element in arr if element!=3]

# if you want to delete a position use "pop" function, suppose 
# position 4 
# the pop function also returns a value
removed_element = arr.pop(4)

# u can also use "del" to delete a position
del arr[4]

0

Ciò rimuove tutte le istanze di "-v"dall'array sys.argve non si lamenta se non sono state trovate istanze:

while "-v" in sys.argv:
    sys.argv.remove('-v')

Puoi vedere il codice in azione, in un file chiamato speechToText.py:

$ python speechToText.py -v
['speechToText.py']

$ python speechToText.py -x
['speechToText.py', '-x']

$ python speechToText.py -v -v
['speechToText.py']

$ python speechToText.py -v -v -x
['speechToText.py', '-x']

-1

questa è la mia risposta, basta usare while e for

def remove_all(data, value):
    i = j = 0
    while j < len(data):
        if data[j] == value:
            j += 1
            continue
        data[i] = data[j]
        i += 1
        j += 1
    for x in range(j - i):
        data.pop()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.