Alle exemplaren van een waarde uit een lijst verwijderen?

In Python zal remove()het eerste voorkomen van waarde in een lijst verwijderen.

Hoe verwijder ik alleinstanties van een waarde uit een lijst?

Dit is wat ik in gedachten heb:

>>> remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
[1, 3, 4, 3]

Antwoord 1, autoriteit 100%

Functionele aanpak:

Python 3.x

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter((2).__ne__, x))
[1, 3, 3, 4]

of

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter(lambda a: a != 2, x))
[1, 3, 3, 4]

Python 2.x

>>> x = [1,2,3,2,2,2,3,4]
>>> filter(lambda a: a != 2, x)
[1, 3, 3, 4]

Antwoord 2, autoriteit 40%

U kunt een lijstbegrip gebruiken:

def remove_values_from_list(the_list, val):
   return [value for value in the_list if value != val]
x = [1, 2, 3, 4, 2, 2, 3]
x = remove_values_from_list(x, 2)
print x
# [1, 3, 4, 3]

Antwoord 3, autoriteit 21%

U kunt slice-toewijzing gebruiken als de originele lijst moet worden gewijzigd, terwijl u toch een efficiënt lijstbegrip (of generatorexpressie) gebruikt.

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> x[:] = (value for value in x if value != 2)
>>> x
[1, 3, 4, 3]

Antwoord 4, autoriteit 7%

De oplossing van de eerste post op een meer abstracte manier herhalen:

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> while 2 in x: x.remove(2)
>>> x
[1, 3, 4, 3]

Antwoord 5, autoriteit 6%

Zie de eenvoudige oplossing

>>> [i for i in x if i != 2]

Hiermee wordt een lijst geretourneerd met alle elementen van xzonder 2


Antwoord 6, autoriteit 2%

Alle antwoorden hierboven (behalve die van Martin Andersson) creëren een nieuwe lijst zonder de gewenste items, in plaats van de items uit de originele lijst te verwijderen.

>>> import random, timeit
>>> a = list(range(5)) * 1000
>>> random.shuffle(a)
>>> b = a
>>> print(b is a)
True
>>> b = [x for x in b if x != 0]
>>> print(b is a)
False
>>> b.count(0)
0
>>> a.count(0)
1000
>>> b = a
>>> b = filter(lambda a: a != 2, x)
>>> print(b is a)
False

Dit kan belangrijk zijn als je andere verwijzingen naar de lijst hebt hangen.

Gebruik een methode als deze om de bestaande lijst aan te passen

>>> def removeall_inplace(x, l):
...     for _ in xrange(l.count(x)):
...         l.remove(x)
...
>>> removeall_inplace(0, b)
>>> b is a
True
>>> a.count(0)
0

Wat snelheid betreft, zijn de resultaten op mijn laptop (allemaal op een 5000 deelnemerslijst met 1000 verwijderde inzendingen)

  • Lijst begrip – ~400us
  • Filteren – ~900us
  • .remove() lus – 50ms

Dus de .remove-lus is ongeveer 100x langzamer…….. Hmmm, misschien is een andere aanpak nodig. De snelste die ik heb gevonden is het gebruik van de lijstbegrip, maar vervang dan de inhoud van de originele lijst.

>>> def removeall_replace(x, l):
....    t = [y for y in l if y != x]
....    del l[:]
....    l.extend(t)
  • removeall_replace() – 450us

Antwoord 7, autoriteit 2%

betere oplossing met lijstbegrip

x = [ i for i in x if i!=2 ]

Antwoord 8

Numpy-benadering en timing tegen een lijst/array met 1.000.000 elementen:

Timingen:

In [10]: a.shape
Out[10]: (1000000,)
In [13]: len(lst)
Out[13]: 1000000
In [18]: %timeit a[a != 2]
100 loops, best of 3: 2.94 ms per loop
In [19]: %timeit [x for x in lst if x != 2]
10 loops, best of 3: 79.7 ms per loop

Conclusie:numpy is 27 keer sneller (op mijn notebook) in vergelijking met de benadering voor het begrijpen van lijsten

PS als je je normale Python-lijst lstnaar numpy array wilt converteren:

arr = np.array(lst)

Instellen:

import numpy as np
a = np.random.randint(0, 1000, 10**6)
In [10]: a.shape
Out[10]: (1000000,)
In [12]: lst = a.tolist()
In [13]: len(lst)
Out[13]: 1000000

Controleer:

In [14]: a[a != 2].shape
Out[14]: (998949,)
In [15]: len([x for x in lst if x != 2])
Out[15]: 998949

Antwoord 9

Ten koste van de leesbaarheid, denk ik dat deze versie iets sneller is omdat het de tijd niet dwingt om de lijst opnieuw te bekijken, dus precies hetzelfde werk doen als verwijderen toch moet doen:

x = [1, 2, 3, 4, 2, 2, 3]
def remove_values_from_list(the_list, val):
    for i in range(the_list.count(val)):
        the_list.remove(val)
remove_values_from_list(x, 2)
print(x)

Antwoord 10

Om alle dubbele exemplaren te verwijderen en er een in de lijst te laten:

test = [1, 1, 2, 3]
newlist = list(set(test))
print newlist
[1, 2, 3]

Hier is de functie die ik heb gebruikt voor Project Euler:

def removeOccurrences(e):
  return list(set(e))

Antwoord 11

a = [1, 2, 2, 3, 1]
to_remove = 1
a = [i for i in a if i != to_remove]
print(a)

Misschien niet de meest pythonische, maar toch de gemakkelijkste voor mij haha


Antwoord 12

Ik geloof dat dit waarschijnlijk sneller is dan op welke andere manier dan ook, als je niet om de volgorde van de lijsten geeft, als je voor de uiteindelijke bestelling zorgt, sla dan de indexen van het origineel op en gebruik die.

category_ids.sort()
ones_last_index = category_ids.count('1')
del category_ids[0:ones_last_index]

Antwoord 13

Laat

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

De eenvoudigste en meest efficiënte oplossing zoals al eerder gepost is

>>> x[:] = [v for v in x if v != 2]
>>> x
[1, 3, 4, 3]

Een andere mogelijkheid die minder geheugen zou moeten gebruiken, maar langzamer zou moeten zijn, is

>>> for i in range(len(x) - 1, -1, -1):
        if x[i] == 2:
            x.pop(i)  # takes time ~ len(x) - i
>>> x
[1, 3, 4, 3]

Timingresultaten voor lijsten met een lengte van 1000 en 100000 met 10% overeenkomende vermeldingen: 0,16 vs 0,25 ms en 23 vs 123 ms.

Timing met lengte 1000

Timing met lengte 100000


Antwoord 14

for i in range(a.count(' ')):
    a.remove(' ')

Veel eenvoudiger geloof ik.


Antwoord 15

Verwijder alle exemplaren van een waarde uit een Python-lijst

lists = [6.9,7,8.9,3,5,4.9,1,2.9,7,9,12.9,10.9,11,7]
def remove_values_from_list():
    for list in lists:
      if(list!=7):
         print(list)
remove_values_from_list()

Resultaat: 6.9 8.9 3 5 4.9 1 2.9 9 12.9 10.9 11

Als alternatief,

lists = [6.9,7,8.9,3,5,4.9,1,2.9,7,9,12.9,10.9,11,7]
def remove_values_from_list(remove):
    for list in lists:
      if(list!=remove):
        print(list)
remove_values_from_list(7)

Resultaat: 6.9 8.9 3 5 4.9 1 2.9 9 12.9 10.9 11


Antwoord 16

Als u geen ingebouwd filterhad of geen extra ruimte wilde gebruiken en u een lineaire oplossing nodig heeft…

def remove_all(A, v):
    k = 0
    n = len(A)
    for i in range(n):
        if A[i] !=  v:
            A[k] = A[i]
            k += 1
    A = A[:k]

Antwoord 17

hello =  ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
#chech every item for a match
for item in range(len(hello)-1):
     if hello[item] == ' ': 
#if there is a match, rebuild the list with the list before the item + the list after the item
         hello = hello[:item] + hello [item + 1:]
print hello

[‘h’, ‘e’, ‘l’, ‘l’, ‘o’, ‘w’, ‘o’, ‘r’, ‘l’, ‘d’]


Antwoord 18

Ik deed dit alleen voor een lijst. Ik ben maar een beginner. Een iets meer gevorderde programmeur kan zeker zo’n functie schrijven.

for i in range(len(spam)):
    spam.remove('cat')
    if 'cat' not in spam:
         print('All instances of ' + 'cat ' + 'have been removed')
         break

Antwoord 19

We kunnen ook alles ter plaatse verwijderen met behulp van delof pop:

import random
def remove_values_from_list(lst, target):
    if type(lst) != list:
        return lst
    i = 0
    while i < len(lst):
        if lst[i] == target:
            lst.pop(i)  # length decreased by 1 already
        else:
            i += 1
    return lst
remove_values_from_list(None, 2)
remove_values_from_list([], 2)
remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
lst = remove_values_from_list([random.randrange(0, 10) for x in range(1000000)], 2)
print(len(lst))

Nu voor de efficiëntie:

In [21]: %timeit -n1 -r1 x = random.randrange(0,10)
1 loop, best of 1: 43.5 us per loop
In [22]: %timeit -n1 -r1 lst = [random.randrange(0, 10) for x in range(1000000)]
g1 loop, best of 1: 660 ms per loop
In [23]: %timeit -n1 -r1 lst = remove_values_from_list([random.randrange(0, 10) for x in range(1000000)]
    ...: , random.randrange(0,10))
1 loop, best of 1: 11.5 s per loop
In [27]: %timeit -n1 -r1 x = random.randrange(0,10); lst = [a for a in [random.randrange(0, 10) for x in
    ...:  range(1000000)] if x != a]
1 loop, best of 1: 710 ms per loop

Zoals we zien dat in-place versie remove_values_from_list()geen extra geheugen nodig heeft, maar het kost zoveel meer tijd om te draaien:

  • 11 secondenvoor waarden voor plaatselijk verwijderen
  • 710 millisecondenvoor lijstbegrippen, die een nieuwe lijst in het geheugen toewijst

Antwoord 20

Niemand heeft een optimaal antwoord gepost voor de complexiteit van tijd en ruimte, dus ik dacht dat ik het een kans zou geven. Hier is een oplossing die alle exemplaren van een specifieke waarde verwijdert zonder een nieuwe array te maken en op een efficiënte tijdcomplexiteit. Het nadeel is dat de elementen de volgordeniet behouden.

Tijdscomplexiteit: O(n)
Extra complexiteit van de ruimte: O(1)

def main():
    test_case([1, 2, 3, 4, 2, 2, 3], 2)     # [1, 3, 3, 4]
    test_case([3, 3, 3], 3)                 # []
    test_case([1, 1, 1], 3)                 # [1, 1, 1]
def test_case(test_val, remove_val):
    remove_element_in_place(test_val, remove_val)
    print(test_val)
def remove_element_in_place(my_list, remove_value):
    length_my_list = len(my_list)
    swap_idx = length_my_list - 1
    for idx in range(length_my_list - 1, -1, -1):
        if my_list[idx] == remove_value:
            my_list[idx], my_list[swap_idx] = my_list[swap_idx], my_list[idx]
            swap_idx -= 1
    for pop_idx in range(length_my_list - swap_idx - 1):
        my_list.pop() # O(1) operation
if __name__ == '__main__':
    main()

Antwoord 21

Over de snelheid!

import time
s_time = time.time()
print 'start'
a = range(100000000)
del a[:]
print 'finished in %0.2f' % (time.time() - s_time)
# start
# finished in 3.25
s_time = time.time()
print 'start'
a = range(100000000)
a = []
print 'finished in %0.2f' % (time.time() - s_time)
# start
# finished in 2.11

Antwoord 22

p=[2,3,4,4,4]
p.clear()
print(p)
[]

Alleen met Python 3


Antwoord 23

Wat is er mis met:

Motor=['1','2','2']
For i in Motor:
       If i  != '2':
       Print(i)
Print(motor)

Anaconda gebruiken

Other episodes