häufigkeiten von strings

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.
picknicker187
User
Beiträge: 3
Registriert: Mittwoch 21. Februar 2007, 23:40

häufigkeiten von strings

Beitragvon picknicker187 » Samstag 17. März 2007, 20:52

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
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Samstag 17. März 2007, 21:18

Das geht schon so wie du beschrieben hast:

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}

Wie du jetzt die Worte nach Häufigkeit sortierst, darfst du selbst rausfinden ;)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Samstag 17. März 2007, 21:22

Auf die schnelle zusammengehackt:

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)


Ist nicht die performanteste Lösung.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Samstag 17. März 2007, 22:07

Verbesserte und schnellerer Version.

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)


BTW: Der ``in`` test sollte schneller sein als ein try...except.

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)


[{4: '43'}, {3: 'blubb'}, {2: 'foobar'}, {2: 'barfoo'}]
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Samstag 17. März 2007, 22:54

Ich will auch ;-)

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)]
>>>

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Samstag 17. März 2007, 23:05

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.

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

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Samstag 17. März 2007, 23:16

Hier noch einer... damit der Gedanke nicht verloren geht und ich endlich mal ein Beispiel für itertools.groupby habe. :-)

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

mfg
Gerold
:-)

PS: Falls jemand fragt... Ja, man kann alles komplizierter machen, als es sein müsste. :twisted:
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Sonntag 18. März 2007, 00:15

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

:roll: :roll: :roll:
EyDu
User
Beiträge: 4866
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Sonntag 18. März 2007, 12:01

Ja, bei so etwas kann man sich einfach nicht zuückhalten :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]


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 = [(x,y) for y,x in sorted([(data.count(x), x) for x in set(data)])]
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Beitragvon birkenfeld » Sonntag 18. März 2007, 13:51

@sape: dein erstes Beispiel im zweiten Post sortiert falsch.
@nkoehring, EyDu: euer Code hat AFAICS quadratische Laufzeit.

Leonidas' Lösung ist am geschicktesten IMO.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
EyDu
User
Beiträge: 4866
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Sonntag 18. März 2007, 14:01

@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 :wink:

EDIT: Da habe ich wohl das Zählen vergessen, dann ist es natürlich quadratische Laufzeit. :roll:
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Sonntag 18. März 2007, 16:23

birkenfeld hat geschrieben:@sape: dein erstes Beispiel im zweiten Post sortiert falsch.
Warum :? Weil '2: foobar' vor '2: barfoo' kommt? Ich weiß auch nicht warum ``sort`` das nicht richtig macht:

Code: Alles auswählen

li = ['2: barfoo', '3: blubb', '2: foobar', '4: 43']
li.sort(reverse=True)
print li


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'}]


Leonidas' Lösung ist am geschicktesten IMO.
Die Lösung sortiert aber nicht.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Sonntag 18. März 2007, 22:30

sape hat geschrieben:
Leonidas' Lösung ist am geschicktesten IMO.
Die Lösung sortiert aber nicht.

Aber sie berechnet die Häufigkeit am klarsten - ohne Exceptions und stattdessen mit Defaultwerten. Den Weg habe ich mir mal von BlackJack abgeschaut.

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 :P

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 Modvoice
EyDu
User
Beiträge: 4866
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Sonntag 18. März 2007, 22:40

Leonidas hat geschrieben:Aber sie berechnet die Häufigkeit am klarsten - ohne Exceptions und stattdessen mit Defaultwerten


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ösen :D
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Sonntag 18. März 2007, 22:47

EyDu hat geschrieben:aber Ziel muss es ja sein, das gesamte Problem mit möglichst undurchsichtigen und einzeiligen List-Comprehensions zu lösen :D

Man könnte auch noch Threads rauspacken, so wie blackbird bei den Es.

Ich glaube wir haben den OP nun sehr effektiv vergrault indem wir aus seinem Thread einen Wettbewerb für Obfuscated Python gemacht haben 8) picknicker187, bist du noch dran?
My god, it's full of CARs! | Leonidasvoice vs Modvoice

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]