häufigkeiten von strings
-
- User
- Beiträge: 3
- Registriert: Mittwoch 21. Februar 2007, 23:40
hi,
ich habe listen mit strings und würde gerne zählen wie oft jeder string in den listen vorkommt und am ende dann die string sortiert nach häufigkeit mit der entsprechenden anzahl ausgeben. also zb: liste: ('bla', 'bla', 'blub, 'hallo')
2:bla
1: blub
1:hallo
ich dachte ich könnte ein string beim ersten fund in ein dict schreiben und als value die 1 dazu, bei jedem weiteren vorkommen dann den value um 1 erhöhen und am schluss dann das dict nach values sortiert ausgeben. aber ich weiss leider nicht wie ich einen value um 1 erhöhen kann und irgendwie macht mir das ganze den eindruck als ob es dafür eine wesentlich einfachere lösung geben müsste. hat jenand eine idee?
gruß und danke,
michi
ich habe listen mit strings und würde gerne zählen wie oft jeder string in den listen vorkommt und am ende dann die string sortiert nach häufigkeit mit der entsprechenden anzahl ausgeben. also zb: liste: ('bla', 'bla', 'blub, 'hallo')
2:bla
1: blub
1:hallo
ich dachte ich könnte ein string beim ersten fund in ein dict schreiben und als value die 1 dazu, bei jedem weiteren vorkommen dann den value um 1 erhöhen und am schluss dann das dict nach values sortiert ausgeben. aber ich weiss leider nicht wie ich einen value um 1 erhöhen kann und irgendwie macht mir das ganze den eindruck als ob es dafür eine wesentlich einfachere lösung geben müsste. hat jenand eine idee?
gruß und danke,
michi
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Das geht schon so wie du beschrieben hast:
Wie du jetzt die Worte nach Häufigkeit sortierst, darfst du selbst rausfinden
Code: Alles auswählen
In [8]: words = ('bla', 'bla', 'blub', 'hallo')
In [9]: frequencies = dict()
In [10]: for word in words:
....: frequencies[word] = frequencies.get(word, 0) + 1
....:
In [11]: frequencies
Out[11]: {'hallo': 1, 'bla': 2, 'blub': 1}
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Auf die schnelle zusammengehackt:
Ist nicht die performanteste Lösung.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def sort_elements_to_frequency(iterable, reverse=True):
freq_dict = dict()
order = list()
for elem in iterable:
try:
freq_dict[elem] += 1
except KeyError, error:
freq_dict[elem] = 1
for k, v in freq_dict.iteritems():
order.append('%s\0%s' % (v, k))
order.sort(reverse=reverse)
return [x.replace('\0', ': ') for x in order]
if __name__ == '__main__':
li = ['blubb', '43', 'foobar', 'barfoo', 'blubb', '43', 'foobar', 'barfoo',
'blubb', '43', '43']
print sort_elements_to_frequency(li)
Verbesserte und schnellerer Version.
BTW: Der ``in`` test sollte schneller sein als ein try...except.
EDIT:
[{4: '43'}, {3: 'blubb'}, {2: 'foobar'}, {2: 'barfoo'}]
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def sort_elements_to_frequency(iterable, reverse=True):
freq_dict = dict()
order = list()
for elem in iterable:
if elem in freq_dict:
freq_dict[elem] += 1
else:
freq_dict[elem] = 1
for k, v in freq_dict.iteritems():
order.append('%s: %s' % (v, k))
order.sort(reverse=reverse)
return order
if __name__ == '__main__':
li = ['blubb', '43', 'foobar', 'barfoo', 'blubb', '43', 'foobar', 'barfoo',
'blubb', '43', '43']
print sort_elements_to_frequency(li)
EDIT:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def sort_elements_to_frequency(iterable, reverse=True):
freq_dict = dict()
order = list()
for elem in iterable:
if elem in freq_dict:
freq_dict[elem] += 1
else:
freq_dict[elem] = 1
order = [{v: k} for k, v, in freq_dict.iteritems()]
order.sort(reverse=reverse)
return order
if __name__ == '__main__':
li = ['blubb', '43', 'foobar', 'barfoo', 'blubb', '43', 'foobar', 'barfoo',
'blubb', '43', '43']
print sort_elements_to_frequency(li)
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Ich will auch
mfg
Gerold
Code: Alles auswählen
>>> baselist = ["aal", "berta", "aal", "zoo", "zoo", "aal"]
>>> words = frozenset(baselist)
>>> words
frozenset(['aal', 'berta', 'zoo'])
>>> counted = {}
>>> for word in words:
... counted[word] = baselist.count(word)
...
>>> counted
{'aal': 3, 'berta': 1, 'zoo': 2}
>>>
# Nachtrag:
>>> counted_list = counted.items()
>>> counted_list
[('aal', 3), ('berta', 1), ('zoo', 2)]
>>> import operator
>>> counted_list.sort(key = operator.itemgetter(1))
>>> counted_list
[('berta', 1), ('zoo', 2), ('aal', 3)]
>>>
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
OK, ich fasse das mal zu einem Programm zusammen. Es wird aber sicher nicht so schnell sein wie das Beispiel von Leonidas, da er die Liste nur einmal durchläuft.
mfg
Gerold
Code: Alles auswählen
import operator
baselist = ["aal", "berta", "aal", "zoo", "zoo", "aal"]
words = frozenset(baselist)
counted_words = []
for word in words:
counted_words.append(
(word, baselist.count(word))
)
counted_words.sort(key = operator.itemgetter(1))
for item in counted_words:
print "%-10s %i" % item
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hier noch einer... damit der Gedanke nicht verloren geht und ich endlich mal ein Beispiel für itertools.groupby habe.
mfg
Gerold
PS: Falls jemand fragt... Ja, man kann alles komplizierter machen, als es sein müsste.
Code: Alles auswählen
import operator
import itertools
baselist = ["aal", "berta", "aal", "zoo", "zoo", "aal"]
sorted_baselist = sorted(baselist)
counted_words = []
for word, items in itertools.groupby(sorted_baselist):
counted_words.append((word, len(list(items))))
counted_words.sort(key = operator.itemgetter(1))
for item in counted_words:
print "%-10s %i" % item
Gerold
PS: Falls jemand fragt... Ja, man kann alles komplizierter machen, als es sein müsste.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- nkoehring
- User
- Beiträge: 543
- Registriert: Mittwoch 7. Februar 2007, 17:37
- Wohnort: naehe Halle/Saale
- Kontaktdaten:
Na dann geb ich auch noch meine Senf dazu ^^
Code: Alles auswählen
>>> tmp
l = ["bla", "bla", "blub", "hallo"]
for i in l:
tmp = list()
for i in l:
if (l.count(i), i) not in tmp: tmp.append((l.count(i), i))
for c, i in tmp:
print str(c)+':', i
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
Ja, bei so etwas kann man sich einfach nicht zuückhalten :
Da hätte ich einen ja fast noch intuitiven Einzeiler:D:
Code: Alles auswählen
data = ["a", "b", "c", "a", "a", "b", "c", "d", "b"]
r = [(data.count(x), x) for x in set(data)]
r.sort()
r = [(x,y) for y,x in r]
Code: Alles auswählen
data = ["a", "b", "c", "a", "a", "b", "c", "d", "b"]
r = [(x,y) for y,x in sorted([(data.count(x), x) for x in set(data)])]
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
@sape: dein erstes Beispiel im zweiten Post sortiert falsch.
@nkoehring, EyDu: euer Code hat AFAICS quadratische Laufzeit.
Leonidas' Lösung ist am geschicktesten IMO.
@nkoehring, EyDu: euer Code hat AFAICS quadratische Laufzeit.
Leonidas' Lösung ist am geschicktesten IMO.
@birkenfeld:
Aber Leonidas Lösung sortiert nicht, das überlässt er dem Benutzer
Mit der quadratischen Laufzeit sehe ich das bei mir etwas anders:
Bilden der Menge in: m = O(n*log n)
Sortieren: s = O(n * log n)
Und das Tauschen, was eigentlich nicht nötig ist: t = O(n)
Macht dann insgesamt (da sequentiell): m + s + t = O(n*log n)
Wir wollen ja nicht schätzen, sondern rechnen
EDIT: Da habe ich wohl das Zählen vergessen, dann ist es natürlich quadratische Laufzeit.
Aber Leonidas Lösung sortiert nicht, das überlässt er dem Benutzer
Mit der quadratischen Laufzeit sehe ich das bei mir etwas anders:
Bilden der Menge in: m = O(n*log n)
Sortieren: s = O(n * log n)
Und das Tauschen, was eigentlich nicht nötig ist: t = O(n)
Macht dann insgesamt (da sequentiell): m + s + t = O(n*log n)
Wir wollen ja nicht schätzen, sondern rechnen
EDIT: Da habe ich wohl das Zählen vergessen, dann ist es natürlich quadratische Laufzeit.
Warum Weil '2: foobar' vor '2: barfoo' kommt? Ich weiß auch nicht warum ``sort`` das nicht richtig macht:birkenfeld hat geschrieben:@sape: dein erstes Beispiel im zweiten Post sortiert falsch.
Code: Alles auswählen
li = ['2: barfoo', '3: blubb', '2: foobar', '4: 43']
li.sort(reverse=True)
print li
Zweiter Post erstes Beispiel:
['4: 43', '3: blubb', '2: foobar', '2: barfoo']
Zweiter Post zweites Beispiel:
[{4: '43'}, {3: 'blubb'}, {2: 'foobar'}, {2: 'barfoo'}]
Die Lösung sortiert aber nicht.Leonidas' Lösung ist am geschicktesten IMO.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Aber sie berechnet die Häufigkeit am klarsten - ohne Exceptions und stattdessen mit Defaultwerten. Den Weg habe ich mir mal von BlackJack abgeschaut.sape hat geschrieben:Die Lösung sortiert aber nicht.Leonidas' Lösung ist am geschicktesten IMO.
Meine Lösung ist insofern genial, da sie dem OP auch etwas zu tun überlässt, so dass er auch etwas lernen kann. Ergo: Edukativ
Nun gut, wir könnten die Lösungen (für beide Probleme: Berechnen und Sortieren) auch später in einer Wikiseite zusammentragen, so wie es in [wiki]Anzahl der Es in einem String[/wiki] der Fall ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Seh' ich auch so, zum Zählen der Vorkommnisse scheint mir dies auch die eleganteste Variante, aber Ziel muss es ja sein, das gesamte Problem mit möglichst undurchsichtigen und einzeiligen List-Comprehensions zu lösenLeonidas hat geschrieben:Aber sie berechnet die Häufigkeit am klarsten - ohne Exceptions und stattdessen mit Defaultwerten
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Man könnte auch noch Threads rauspacken, so wie blackbird bei den Es.EyDu hat geschrieben:aber Ziel muss es ja sein, das gesamte Problem mit möglichst undurchsichtigen und einzeiligen List-Comprehensions zu lösen
Ich glaube wir haben den OP nun sehr effektiv vergrault indem wir aus seinem Thread einen Wettbewerb für Obfuscated Python gemacht haben picknicker187, bist du noch dran?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nee, nee, so war meine Lösung nicht gemeint, sondern eher ein Vorschlag wie man es noch machen könnte. Und ich muss sagen, dieser Thread hat doch ganz brauchbare Variationen hervorgebracht, wie man an so ein Problem herangehen kann, auch wenn man sie eventuell als Einsteiger nicht sofort versteht.Leonidas hat geschrieben:Man könnte auch noch Threads rauspacken, so wie blackbird bei den Es.
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
Nein, weil "10: barfoo" vor "1: barfoo" kommt.sape hat geschrieben:Warum Weil '2: foobar' vor '2: barfoo' kommt?birkenfeld hat geschrieben:@sape: dein erstes Beispiel im zweiten Post sortiert falsch.
Ja, mit einstelligen Zahlen funktioniert es schon. Mit mehrstelligen nicht.Ansonsten sehe ich nicht wo falsch sortiert wird:
Zweiter Post erstes Beispiel:
['4: 43', '3: blubb', '2: foobar', '2: barfoo']
Zweiter Post zweites Beispiel:
[{4: '43'}, {3: 'blubb'}, {2: 'foobar'}, {2: 'barfoo'}]
Ja, das ist trivial anzuhängen.Die Lösung sortiert aber nicht.Leonidas' Lösung ist am geschicktesten IMO.
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi,birkenfeld hat geschrieben:Nein, weil "10: barfoo" vor "1: barfoo" kommt.sape hat geschrieben:Warum Weil '2: foobar' vor '2: barfoo' kommt?birkenfeld hat geschrieben:@sape: dein erstes Beispiel im zweiten Post sortiert falsch.
das Problem kenne ich nur zu gut. Der Doppelpunkt hat den Characterwert 58, Zahlen aber kleinere. Dadurch werden kürzere Zahlen nach unten sortiert. Wenn es nur um die Ausgabe geht, kann man die Zahlen vorn mit Leerzeichen auffüllen, die stehen dann oben:
Code: Alles auswählen
iMax = max(frequencies)
l = ["%*s: %s" % (iMax, iAnzahl, sString) for sString, iAnzahl in frequencies.items()]
l.sort()
Grüße,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
Ja, man kann auch über China nach Amerika fliegen. Man kann aber auch einfach die Zahlen als Integers belassen und sortieren, anstatt sie vorher in Strings umzuwandeln.
Birkenfeld und Michael, danke für euren Hinweiß, das hatte ich nicht beachtet.
EDIT: Hab nochmal meine zweite variante (im zweiten post) getestet und die scheint zu gehen
Zweite vom zweiten Post:
[{10: 'barfoo'}, {4: '43'}, {3: 'blubb'}, {1: 'foobar'}]
EDIT: Hab nochmal meine zweite variante (im zweiten post) getestet und die scheint zu gehen
Zweite vom zweiten Post:
[{10: 'barfoo'}, {4: '43'}, {3: 'blubb'}, {1: 'foobar'}]