Doppelte Elemente entfernen ohne Reihenfolge zu ändern

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.
Antworten
mickimick
User
Beiträge: 4
Registriert: Samstag 31. August 2013, 19:20

Hallo zusammen,

ich habe eine kurze Frage. Und zwar will ich aus einer Liste doppelte Elemente entfernen. Das geht ja beispielsweise mit set(). Nur habe ich das Problem, dass dies meine Reihenfolge ändert. Da ich das nicht möchte bin ich auf der Suche nach einer anderen Möglichkeit. Kann mir da jemand helfen?

Wär super!
Danke!
mathematik
User
Beiträge: 28
Registriert: Dienstag 16. April 2013, 12:40

Hey mickimick,

du kannst für eine Liste
  • L=[1,2,3,3,4,4,5,6]

Code: Alles auswählen

sorted(list(set(L))
verwenden. Das gibt dir dann das gewünschte Ergebnis
  • L=[1,2,3,4,5,6]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

So könnte man es machen:

Code: Alles auswählen

source = [7, 1, 2, 6, 1, 3, 2, 1, 6, 5, 3]
result = []
found = set()

for item in source:
    if item not in found:
        found.add(item)
        result.append(item)

result
> [7, 1, 2, 6, 3, 5]
@mathematik: Deine Lösung setzt voraus, dass die Ursprungsliste sortiert vorliegt!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

oder mit Hilfe von collections:

Code: Alles auswählen

from collections import OrderedDict
result = OrderedDict(zip(source,source)).keys()
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@mickimick:
Deine Frage ist nicht klar - Was ist denn die gewünschte Reihenfolge? Welches Vorkommen von x bestimmt diese? Die hier gezeigten Varianten gehen davon aus, dass das erste Vorkommen die Reihenfolge bestimmt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@jerch: in diese Falle tappt man auch als fortgeschrittener Forumsteilnehmer immer mal wieder.
Hier natürlich die "richtige" Lösung, die nach der mittleren Position der Elemente sortiert: :wink:

Code: Alles auswählen

def iindex(elements, value):
    try:
        k=0
        while True:
             k=elements.index(value, k+1)
             yield k
    except ValueError:
        pass

result = [x for _pos,x in sorted((sum(iindex(source, x))/float(source.count(x)), x) for x in set(source))]
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Code: Alles auswählen

def uniquify_keep_first_found(iterable):
    seen = set()
    seen_add = seen.add
    return (
        each for each in iterable if each not in seen and not seen_add(each))

def uniquify_keep_last_found(iterable):
    from operator import itemgetter
    get_second = itemgetter(1)
    last_seen = {}
    for i, each in enumerate(iterable):
        last_seen[each] = i
    return (each for each, _ in sorted(last_seen.items(), key=get_second))

print(list(uniquify_keep_first_found([1, 2, 3, 4, 3, 4, 3, 6, 2, 8, 9, 8])))
print(list(uniquify_keep_last_found([1, 2, 3, 4, 3, 4, 3, 6, 2, 8, 9, 8])))
Ergebnis:

Code: Alles auswählen

$ python uniqui.py
[1, 2, 3, 4, 6, 8, 9]
[1, 4, 3, 6, 2, 9, 8]
In specifications, Murphy's Law supersedes Ohm's.
lunar

@pillmuncher Ich finde es fragwürdig, Generatorausdrücke mit Seiteneffekten zu schreiben, und der kleine Trick mit "and", der sich noch dazu auf den undokumentierten Rückgabewert von "set.add()" verlässt, macht es nicht besser.

Mag sein, dass Du das anders siehst, doch ich finde diese Lösung weder elegant noch schön noch cool(TM), sondern schlicht fahrlässig.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@lunar: Vielleicht gefällt dir ja das hier besser:

Code: Alles auswählen

def uniquify_keep_first_found(iterable):
    seen = {}
    seen_setdefault = seen.setdefault
    return (seen_setdefault(e,e) for e in iterable if e not in seen)
In specifications, Murphy's Law supersedes Ohm's.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Was wohl hier die gesuchte Reihenfolge ist:

Code: Alles auswählen

[0,0,2,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,1,0,0,0,1,2,0,0,0,1,0,2,0,2,0,0,0,0,1,0,0,0,2,0,0,0,0]
:twisted:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@jerch:

Code: Alles auswählen

[0, 2, 1]
Das Leben ist wie ein Tennisball.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Immer wieder schön, wenn Threadersteller nach ihrer Frage nichts mehr von sich hören lassen. :)
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@EyDu: Ich wollte damit auf die Verteilung hinaus, wenn man das mal plottet, kommt man eher auf [0,1,2]. Das Beispiel sollte eigentlich nur zeigen, dass es viele Kriterien der "Reihenfolge" gibt (von ntem Vorkommen über Mittelwerte bis komplexe Verteilungsmodelle) und ohne weitere Angaben da nur Rätselraten angesagt ist.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also im Kontext einer Python-Liste ist das Wort Reihenfolge imho eindeutig belegt, nämlich durch die Reihenfolge der Listenelemente! Ich finde in diesem Falle müsste man ganz im Gegenteil explizit benennen, dass man eine andere Reihenfolge meint.

Darüber hinaus fügt der OP zusätzlich an, dass ``set`` die "Reihenfolge" durcheinander bringt - was ein weiteres Indiz dafür ist, dass der OP die Reihenfolge der Elemente meint.

Unglücklich an seiner Formulierung ist lediglich das "meine" - erst dadurch könnte man verleitet werden zu glauben, es handele sich um eine spezielle Reihenfolge. Vermutlich ist das aber eher eine Schwäche in der Diktion ;-)

@snafu: Tja, da kann man nix machen ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Hyperion hat geschrieben:Also im Kontext einer Python-Liste ist das Wort Reihenfolge imho eindeutig belegt, nämlich durch die Reihenfolge der Listenelemente!
Seh ich auch so. Nur ist die "Reduktion" eben nicht definiert. Wen ich mit einem Würfel

Code: Alles auswählen

2,6,3,6
würfle, ist eben das die Reihenfolge, wie will man das reduzieren, ohne die "Reduktionsregeln" zu kennen? Danach habe ich gefragt.
lunar

@pillmuncher Nun, auch dieser Generatorausdruck hat immer noch einen Seiteneffekt, nicht wahr? Ich fände eine for-Schleife mit "yield" besser...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

jerch hat geschrieben:Nur ist die "Reduktion" eben nicht definiert.
Stand doch gleich im ersten Posting:
mickimick hat geschrieben:Und zwar will ich aus einer Liste doppelte Elemente entfernen.
;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Hyperion:
Liest Du in die Aussage nicht ein bisschen viel rein?

Ok doppelte Elemente entfernen:

Code: Alles auswählen

[1,2,3,2,3,3]-->[1,3,3,3]
:twisted:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

jerch hat geschrieben:@Hyperion:
Liest Du in die Aussage nicht ein bisschen viel rein?

Ok doppelte Elemente entfernen:

Code: Alles auswählen

[1,2,3,2,3,3]-->[1,3,3,3]
:twisted:
Also ehrlich gesagt legst Du zu viel Präzision in die Frage des OP 8)

Jaja, von dreifach vorkommenden schreibt er ja auch nichts... :P
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten