Doppelte Elemente einer Liste elegant entfernen

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.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Doppelte Elemente einer Liste elegant entfernen

Beitragvon numerix » Dienstag 28. Oktober 2008, 19:09

Wie würdet ihr die Elemente einer Liste, die doppelt vorkommen, entfernen?
Nein, ich meine nicht die Reduktion auf je ein Exemplar pro Element (also z.B. über Umwandlung in ein set), sondern die vollständige Entfernung dieser Elemente, so dass nur noch die Elemente übrigbleiben, die einmalig waren.

Konkret handelt es sich bei den Listenelementen um Tupel mit Zahlenwerten.

Meine erste Lösung sieht so aus, dass ich ein set der Liste anfertige, dieses durchlaufe und prüfe, ob die Anzahl der einzelnen Elemente in der Liste größer als 1 ist. Wenn ja, werden sie aus der Liste entfernt. Funktional einwandfrei.

ABER: Ist nicht elegant. Wie kann man das schöner lösen? (Performance ist nicht das Problem. Die Liste ist nicht lang.)
BlackJack

Beitragvon BlackJack » Dienstag 28. Oktober 2008, 19:26

Ungetestet:

Code: Alles auswählen

histogram = defaultdict(int)
for item in list_a:
    histogram[item] += 1
result = [x for x in list_a if histogram[x] == 1]


Erhält sogar die Reihenfolge der Werte aus `list_a`.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Dienstag 28. Oktober 2008, 19:48

Jop, schließe mich BlackJack an; ``collections.defaultdict`` war mein erster Gedanke.

Alternativ vielleicht von ``set`` (oder gleich ``list``) so ableiten, dass ``add()`` (bzw. ``__setitem__()``[?]) bei der Anweisung, ein bereits vorhandenes Element hinzuzufügen, dieses direkt löscht und das übergebene Element verwirft. Je nachdem, in welchem Umfang du das nutzen willst.
lunar

Beitragvon lunar » Dienstag 28. Oktober 2008, 20:49

Y0Gi hat geschrieben:Alternativ vielleicht von ``set`` (oder gleich ``list``) so ableiten, dass ``add()`` (bzw. ``__setitem__()``[?]) bei der Anweisung, ein bereits vorhandenes Element hinzuzufügen, dieses direkt löscht und das übergebene Element verwirft. Je nachdem, in welchem Umfang du das nutzen willst.

Dann benötigt man aber ein "set" im "set", um die Liste der bereits verworfenen Elemente zu speichern. Ansonsten führt nämlich der dritte "set.add()" Aufruf dazu, dass das Element wieder hinzugefügt wird.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Dienstag 28. Oktober 2008, 22:35

Vielen Dank für eure Vorschläge. Die Idee mit dem dictionary ist interessant.

Die Ausführungen von Y0Gi haben noch eine andere Erleuchtung mit sich gebracht: Da die besagte Liste zuvor vom Programm selbst erzeugt wird, und zwar sukzessive via append, ist es natürlich am schlauesten, ein schon vorhandenes Element gar nicht erst erneut anzuhängen, sondern das schon vorhandene stattdessen zu löschen ...
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Mittwoch 29. Oktober 2008, 12:54

lunar: Guter Einwand, bei einem allgemeineren Szenario (Elemente können auch mehr als zweimal vorkommen) muss man natürlich eine Liste der Duplikate führen.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Donnerstag 29. Januar 2009, 16:51

Ups, Spam zitiert - jetzt entfernt.
Zuletzt geändert von numerix am Donnerstag 29. Januar 2009, 17:55, insgesamt 1-mal geändert.
lunar

Beitragvon lunar » Donnerstag 29. Januar 2009, 16:56

Spam ...
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Beitragvon hendrikS » Donnerstag 29. Januar 2009, 16:56

Eine Kombination aus set, count und remove sollte auch zum Erfolg fuehren.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Donnerstag 29. Januar 2009, 17:19

User + Posting gelöscht, aber durch das Zitat ist der Spam immer noch da...
numerix hat geschrieben: :?:

Was ich mich ja frage, warum zitiert man denn Spam?

Edit: Danke fürs ausbessern, numerix.
Zuletzt geändert von Leonidas am Donnerstag 29. Januar 2009, 17:57, insgesamt 1-mal geändert.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Beitragvon hendrikS » Donnerstag 29. Januar 2009, 17:33

Hier meine Lösung:

Code: Alles auswählen

a = [3,4,3,5,3,2,2,1]
print [i for i in set(a) if a.count(i)<2]


Aber ich denke, es ist Jacke wie Hose. BlackJacks ist auch nicht schlecht.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Beitragvon HWK » Donnerstag 29. Januar 2009, 17:48

@hendrikS: Deins ist zwar weniger Quellcode, dürfte bei langen Listen aber deutlich länger brauchen, da count() die Liste ja jedesmal neu durchlaufen muss.
MfG
HWK
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Beitragvon HerrHagen » Donnerstag 29. Januar 2009, 17:54

Das set brauchts in dem Code von hendrikS nich.

Code: Alles auswählen

>>> a = [3,4,3,5,3,2,2,1]
>>> [i for i in a if a.count(i)<2]
[4, 5, 1]

So bleibt auch die Reihenfolge gewahrt.
Find ich persönlich viel eleganter als die defaultdict Variante.

EDIT: @HWK: Ich denk auf Zeit kommts nicht an?
Zuletzt geändert von HerrHagen am Donnerstag 29. Januar 2009, 17:56, insgesamt 1-mal geändert.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Donnerstag 29. Januar 2009, 17:56

Leonidas hat geschrieben:User + Posting gelöscht, aber durch das Zitat ist der Spam immer noch da...
numerix hat geschrieben: :?:

Was ich mich ja frage, warum zitiert man denn Spam?


Ich dachte tatsächlich, der hätte sich was dabei gedacht ... :oops:

Im übrigen war das ursprüngliche Problem in diesem Thread schon gelöst ...
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Beitragvon HerrHagen » Donnerstag 29. Januar 2009, 17:58

oh, ich seh grad - ist schon etwas länger her...

Wer ist online?

Mitglieder in diesem Forum: Google [Bot]