remove_all für Liste

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

Hallo,


mal eine Frage, wie kann ich aus einer Liste/Hash alle Einträge löschen für ein gesuchtes Wort und
nicht nur den ersten Treffer?

Mit

Code: Alles auswählen

testarray.remove('test') # löscht den ersten Treffer aus der Liste
lösche ich das erste 'test', das sich im testarray befindet.

Wenn der Array aber 5x das Wort 'test' beinhaltet, wie kann ich dann direkt alle 5 Treffer auf einmal löschen?
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Entweder löschst sie nacheinander:

Code: Alles auswählen

>>> x = [1,2,3,1,2,1,2,4,3,2,1]
>>> val = 1
>>> while True:
...     try:
...         x.remove(val)
...     except ValueError:
...         break
>>> x
0: [2, 3, 2, 2, 4, 3, 2]
oder du erstellt eine neue Liste:

Code: Alles auswählen

>>> x = [1,2,3,1,2,1,2,4,3,2,1]
>>> filter(lambda v:v!=1, x)
2: [2, 3, 2, 2, 4, 3, 2]
>>> [v for v in x if v!=1]
3: [2, 3, 2, 2, 4, 3, 2]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Spontan fiel mir das ein:

Code: Alles auswählen

In [8]: from itertools import repeat

In [10]: map(l.remove, repeat("test", l.count("test")))
Out[10]: [None, None]

In [11]: l
Out[11]: ['foo', 'bar']
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Barcellona
User
Beiträge: 74
Registriert: Dienstag 25. Mai 2010, 12:10

Danke schön für die Antworten!

Es sollte mal sowas wie eine remove_all() Funktion für Listen in Python implementiert werden...
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

HerrHagen: also ich bevorzuge ja die funktionale Variante 8)

Code: Alles auswählen

>>> from operator import ne
>>> from functools import partial
>>> x = [1,2,3,1,2,1,2,4,3,2,1]
>>> filter(partial(ne, 1), x)
[2, 3, 2, 2, 4, 3, 2]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich will auch noch eine Runde:

Code: Alles auswählen

reduce(lambda x, y: x+[y] if y!=1 else x, [1,2,3,6,4,8,9,2,5,1,6,3], [])
Oder gar so:

Code: Alles auswählen

reduce(lambda ys, x: (ys, ys[x!=1].append(x))[0], [1,2,3,6,4,8,9,2,5,1,6,3], ([], []))[1]
Das Leben ist wie ein Tennisball.
BlackJack

So viele Lösungen und nur zwei die was taugen. Das wären die, bei denen eine neue Liste mit `filter()` erstellt wird. Die anderen gehen die Liste mehrmals durch, oder haben sogar quadratische Laufzeit.
problembär

Code: Alles auswählen

while 'test' in testarray:
    testarray.remove('test')
In Python ist meine Priorität in der Regel nicht Geschwindigkeit, sondern Verständlichkeit.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

problembär: Von der Lesbarkeit her ist deine Lösung wirklich die beste!
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Ich hätte da noch die Schul-Informatik-Unterricht-Lösung:

Code: Alles auswählen

MeineListe = list(['dies','ist','ein','test','test','test'])
try:
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
    MeineListe.remove('test')
except:
    print 'Fertig!!1'
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
pillmuncher
User
Beiträge: 1531
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Statt prozedural zu denken "wie kann ich alle ... löschen", lieber deklarativ: "dieselbe Liste, aber ohne alle ...":

Code: Alles auswählen

>>> data = ['foo', 'test', 'bar', 'test', 'zig', 'test', 'zag', 'test']
>>> print data
['foo', 'test', 'bar', 'test', 'zig', 'test', 'zag', 'test']
>>>
>>> data[:] = [each for each in data if each != 'test']
>>> print data
['foo', 'bar', 'zig', 'zag']
@problembär: das ist IMO maximal verständlich und zudem GWDW*.

Gruß,
Mick.

[*]Gschwind wia da Wind.
In specifications, Murphy's Law supersedes Ohm's.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

pillmuncher hat geschrieben:Statt prozedural zu denken "wie kann ich alle ... löschen", lieber deklarativ: "dieselbe Liste, aber ohne alle ..."
Da warst du wohl schneller, wäre auch meine Idee gewesen. :wink:
Das ist ganz klar die beste und verständlichste Lösung!
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Benutzeravatar
snafu
User
Beiträge: 6881
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Defnull hat geschrieben:Ich hätte da noch die Schul-Informatik-Unterricht-Lösung:
Ich find die super. :)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

ms4py hat geschrieben:
pillmuncher hat geschrieben:Statt prozedural zu denken "wie kann ich alle ... löschen", lieber deklarativ: "dieselbe Liste, aber ohne alle ..."
Da warst du wohl schneller, wäre auch meine Idee gewesen. :wink:
Das ist ganz klar die beste und verständlichste Lösung!
Diese Variante hatte HerrHagen doch schon gezeigt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

problembär hat geschrieben:

Code: Alles auswählen

while 'test' in testarray:
    testarray.remove('test')
In Python ist meine Priorität in der Regel nicht Geschwindigkeit, sondern Verständlichkeit.
Hm... der Test im Schleifenkopf ist aber teuer. HerrHagen hatte das mit der Exception imho schöner gelöst. Am lesbarsten (und auch am schnellsten) ist wirklich die Lösung mit filter bzw. der äquivalenten List comprehension.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6881
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich finde die LC wesentlich lesbarer als die Variante mit `filter()`.

Hier mal ein bißchen erweitert:

Code: Alles auswählen

In [1]: def remove_all(iterable, deletion):
   ...:     it = type(iterable)
   ...:     return it(elem for elem in iterable if elem != deletion)
   ...: 

In [2]: remove_all((3,2,4,6,4,3,2,5,3,2,1), 3)
Out[2]: (2, 4, 6, 4, 2, 5, 2, 1)
lunar

@snafu: Durch die Typmagie funktioniert die Funktion faktisch nur mit Listen und Tupeln, nicht aber mit beliebigen Iteratoren. Der Name "iterable" verspricht daher mehr, als die Funktion halten kann. Wenn Du ein "iterable" akzeptierst, dann gibt auch wieder ein "iterable" zurück. Dann kann man immer noch einen anderen Konstruktor aufrufen, wenn man das möchte ... allerdings bleibt von der Funktion dann eigentlich nicht mehr genug übrig, um sie noch als Funktion zu implementieren.
Benutzeravatar
snafu
User
Beiträge: 6881
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

In welchem konkreten Fall sollte sich die Funktion denn deiner Meinung nach nicht so verhalten, wie man es bei einem `iterable`-Argument erwartet?
BlackJack

@snafu: Es geht darum, dass es sich nicht nur wie ein "iterable" verhalten muss. Ein "iterable" wäre zum Beispiel ein Generatorausdruck. Damit kommt die Funktion aber nicht klar. Deshalb ist der Name sehr irreführend.
Benutzeravatar
snafu
User
Beiträge: 6881
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Okay, ich hätte die Funktion wirklich mit verschiedenen anderen Typen testen sollen. Da hab ich gestern offenbar gepennt.
Antworten