Liste -> Mehrfacheinträge eliminieren und zählen

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
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Hallo,

diesmal wollte ich es eigendlich alleine schaffen....
Aber ich komme einfach nicht weiter.

Ich habe eine dyn. generierte Liste.
In dieser Liste können Einträge mehrfach vorkommen.
beispiel_liste = ['Hund','Katze','Hund','Maus','Hund']
Ich möcht die Listeneinträge in eine Datei schreiben, aber nicht so:

Hund
Hund
Hund

sondern

Hund : Trefferanzahl=3
Katze: Trefferanzahl=1....


ich habe jetzt schon eingie Ansätze versucht, aber nichts klappt so wirklich.

Ich weiss nicht wie ich diese Abfrage umsetzen soll.
Habe es mit gleichen Listen versucht (und rausgefunden, das kopierte Listen ganz anders reagieren als "gleiche" Listen -> Referenz auf Liste?!)

Idee:

Liste1 = B,B,B
Liste2 = B,B,B
vgl. Liste1[0] mit Liste2[0] ->True -> Zähler = Zähler + 1, del Liste2[0]

Liste1 = B,B,B
Liste2 = X,B,B

...ihr versteht sicher was ich meine, aber es funktioniert nicht, da der Zustand von Liste2 (glaube ich) so ist:

Liste2 = B,B und Liste1 jetzt auf den index[1] von Liste 2 Springt, also das zweite und letzte B

OK, hoffentlich nicht zu chaotisch formuliert
Hier mein letzter (missglückter) versuch:

Code: Alles auswählen

liste_1 = ['1','1','3','1']
liste_2 = ['1','1','3','1']

for zahl1 in liste_1:
    a=1
    liste_3 = []
    print "\n\nzalh1 ist:",zahl1,"\n"
    for zahl2 in liste_2:
        print "Vergleiche zalh1:",zahl1,"\n"
        print "mit zalh2:",zahl2,"\n---------"
        if zahl1 == zahl2:
            print "die Zahlen sind gleich\n---"
            liste_3.append(zahl1)
            print "liste_3:",liste_3,"\n"
            liste_2.remove(zahl2)
            print "liste_2:",liste_2,"\n"
        else:
            print "die Zahlen sind ungleich\n"
bei diesem Versuch, wollte ich alle gleichen Einträge in Liste_3 schreiben
und dann die Anzahl über len() oder ähnlich ausgeben, aber bei mehr als einem Eintrag bekomme ich len(n-1) -> hoffe ich habe das richtig beobachtet

würde mich über eure Tipps freuen :)

Grüße,christine
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Du kannst doch einfach die Werte in einem Dictionary speichern:

Code: Alles auswählen

x = {Hund: 3, Something: 1, ...}
Gehst du halt einfach die Liste durch und addest entweder einen neuen Key oder inkrementierst, falls der Key schon vorhanden ist, den Wert des Keys ;)
Ich hab mir jetzt nicht alles genau durchgelesen, aber am Anfang stand ja, dass du eigentlich sowas haben willst.

Edit:
Habe es mit gleichen Listen versucht (und rausgefunden, das kopierte Listen ganz anders reagieren als "gleiche" Listen -> Referenz auf Liste?!)
http://www.python-forum.de/topic-17228.html
Da wird glaube ich sowas in der Richtung erklärt, wie du das meinst, wenn ich den Thread richtig in Erinnerung habe.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin christine,

defaultdict ist hier wohl das richtige:

Code: Alles auswählen

from collections import defaultdict
pets = ["Hund", "Katze", "Maus", "Hund", "Hund", "Katze"]
counted = defaultdict(int)
for pet in pets:
    counted[pet] += 1
counted
# defaultdict(<type 'int'>, {'Katze': 2, 'Hund': 3, 'Maus': 1})
Gibt es einen Key nicht schon im Dictionary, dann ruft defaultdict den übergebenen Konstruktor auf (hier int) und weißt den zurückgegebenen Wert dem fehlenden Key zu.

Gruß,
Manuel
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Hm, cool, mit defaultdict geht das ja _noch_ einfacher, kannte ich noch gar nicht :)

Wenn du dann die Keys und die zugehörigen Werte wieder auslesen willst, musst du dann nur noch folgendes machen:

Code: Alles auswählen

for i in counted.keys():
    print i, counted[i]
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Nocta hat geschrieben:Hm, cool, mit defaultdict geht das ja _noch_ einfacher, kannte ich noch gar nicht :)

Wenn du dann die Keys und die zugehörigen Werte wieder auslesen willst, musst du dann nur noch folgendes machen:

Code: Alles auswählen

for i in counted.keys():
    print i, counted[i]
In deinem Beispiel kannst du dir auch das ".keys()" sparen ;-).
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Ups, ja stimmt :p
BlackJack

Und wenn man eh beides haben will, kann man auch gleich über die Paare iterieren:

Code: Alles auswählen

for animal, count in counted.iteritems():
    print '%s: %d' % (animal, count)
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Als Alternative zu defaultdict kann man auch mit set arbeiten. Ist Geschmackssache.

z.Bsp. so:

Code: Alles auswählen

pets = ["Hund", "Katze", "Maus", "Hund", "Hund", "Katze"]
for pet in set(pets): print pet, pets.count(pet)
BlackJack

@hendrikS: Wer mag denn bitteschön quadratische Laufzeit, wenn er lineare haben kann!?
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Ich hab das Zeitargument von BlackJack mal kurz gecheckt mit einer Hunde, Katze, Maus Liste von ungefähr 20000 Einträgen. Ist bei beiden Lösungen etwa identisch. Möglicherweise habe ich aber nicht genuegend Testfälle gehabt.
Weiss nicht genau wie Du auf quadratisch kommst?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

hendrikS hat geschrieben: Weiss nicht genau wie Du auf quadratisch kommst?
Weil Du in der äußeren Schleife die Anzahl an pets durchläufst und dann in der inneren bei jedem einzelnen Durchlauf auch! -> Laufzeit quadratisch!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

hendrikS hat geschrieben:Ich hab das Zeitargument von BlackJack mal kurz gecheckt mit einer Hunde, Katze, Maus Liste von ungefähr 20000 Einträgen. Ist bei beiden Lösungen etwa identisch.
Dann war dein ``n`` zu klein. Schau her was es für tolle Caches gibt und wie gut Python optimiert ist :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Ich habe noch mal n'bisschen performance mit timeit gecheckt.
Also speziell, wenn die Anzahl verschiedener Elemente zunimmt (so ab >6) wir die Performance meiner Lösung stetig schlechter :cry: .
Na ja. Sei's drum. Die schnellere Lösung sollte immer den Vorzug haben. Also klares Votum fuer defaultdict.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

hendrikS hat geschrieben:Die schnellere Lösung sollte immer den Vorzug haben.
Nicht unbedingt.

Code: Alles auswählen

import this
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Hey,
ihr seid echt super!
Ich nehme jetzt die Lösung von helduel.
Musste aber erst noch von 2.4 auf 2.5 umsteigen :wink:

Ich finde die ganze Diskussion super hilfreich.
Mit set() hatte ich auch schon etwas herumversucht, aber auf eine richtige Lösung bin ich da von selbst nicht gekommen :roll:
Oft weiss ich nicht wie was syntaktisch umzusetzen ist.
Und nat. auch nicht was es alles für Module und Einsatzmöglichkeiten gibt.

Also, vielen vielen Dank @ all
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Mal ne Frage, wenn ich dieses Defaultdict jetzt sortiert nach Häufigkeit ausgeben will, gibt es dann noch was einfacheres als dies hier?

Code: Alles auswählen

for i in sorted([(x, y) for x, y in counted.iteritems()], lambda x, y: y[1] - x[1]):
    print i[0], i[1]
Ich finde die Lösung zwar nicht schlecht und auch gut verständlich, aber vielleicht kann mir ja wieder jemand etwas neues aufzeigen, wie das so oft hier im Forum passiert.
lunar

Code: Alles auswählen

for key, item in sorted(counted.iteritems(), key=itemgetter(1)):
    print(key, item, sep=': ')
"itemgetter()" kommt aus dem "operator"-Modul.
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Hallo,
ich sortiere meine Ausgabe auch:

Code: Alles auswählen

counted = defaultdict(int) 
for ergebnisWort in ergebnisListeDerAbfrage:
     counted[ergebnisWort] += 1 

sortierung = sorted((value, key) for (key, value) in counted.iteritems())
sortierung.reverse()
for key, value in sortierung:
     print "Treffer: %d %s" % (key, value)
Erhalte dann folgende Ausgabe:

Code: Alles auswählen

Treffer: 4 Bekleidungsgeschäfts 
Treffer: 2 Weisungsrecht 
Treffer: 2 Geschäftslokal 
Treffer: 2 Geschäfte 
Treffer: 1 Gewerbemiete 
Treffer: 1 Geschäftsraummietvertrag 
8)
Antworten