Häufigsten Buchstaben herausfinden

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
_nohtyp_
User
Beiträge: 127
Registriert: Mittwoch 8. Januar 2014, 15:38

Ich versuche mich gerade an checkio.org. Mein Code:

Code: Alles auswählen

def checkio(text):
    text = text.lower()
    text = text.replace(" ", "")
    alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
    
    high = [0, ""]
    
    for x in alphabet:
        if text.count(x) > high[0]:
            high = [text.count, x]
            
    print high
Es kommt leider folgende Meldung:

Code: Alles auswählen

[<built-in method count of str object at 0xe33f00>, 'd']
Bitte keine Lösungsansätze geben :wink: Ich verstehe nur die Meldung nicht.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

_nohtyp_ hat geschrieben:Bitte keine Lösungsansätze geben :wink: Ich verstehe nur die Meldung nicht.
Das Problem ist:

Code: Alles auswählen

high = [text.count, x]
...was du in deinem Code nach positiv ausgefallenem Test definierst. Ich vermute stark, es geht dir um das Ergebnis von ``text.count(x)``. Das müsstest du dann auch genau so hinschreiben. Mit deinem bisherigen Code wird halt die ``count()``-Methode als erstes Objekt in die Liste gepackt und eben nicht das Ergebnis ihres Aufrufs.
BlackJack

@_nohtyp_: Du willst ja keine Lösungsansätze hören, darum nur so viel: Das ist der ”falsche”. Das wird zwar funktionieren ist aber von der Laufzeit her unnötig umständlich. Und auch vom Code her, denn die Standardbibliothek bietet dafür ein verdammt nützliches Werkzeug (im `collections`-Modul).
_nohtyp_
User
Beiträge: 127
Registriert: Mittwoch 8. Januar 2014, 15:38

Danke. Das collections-Modul hat geholfen :D
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Numpy hat Statistikfunktionen die Dir Histogramme (welcher Wert kommt wie oft vor) erstellen können. Hier meine Lösung, die allerdings nicht mit Unicode klarkommt, weil alle Buchstaben zu uint8 umgewandelt werden.

Code: Alles auswählen

text = """
Ich versuche mich gerade an checkio.org. Mein Code:
Code: [Alles auswaehlen] [Aufklappen/Zusammenklappen]

    def checkio(text):
        text = text.lower()
        text = text.replace(" ", "")
        alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
       
        high = [0, ""]
       
        for x in alphabet:
            if text.count(x) > high[0]:
                high = [text.count, x]
               
        print high

Highlighting by GeSHi


Es kommt leider folgende Meldung:
Code: [Alles auswaehlen] [Aufklappen/Zusammenklappen]

    [<built-in method count of str object at 0xe33f00>, 'd']
"""

import numpy as N

numpy_text = N.array([text]) # 1 Element der Laenge 701
numpy_text.dtype = N.uint8 # 701 Elemente der Laenge 1

anzahlProBuchstabe = N.bincount(numpy_text)

buchstaben = N.array(N.arange(anzahlProBuchstabe.size), dtype=N.uint8)
buchstaben.dtype = "|S1"

for c, n in zip(buchstaben, anzahlProBuchstabe):
    print( repr(c), n )
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@MagBen: Und das hat jetzt genau welchen Mehrwert im Vergleich zu der Zähler-Klasse, die Python schon in der Standardbibliothek mitbringt?
BlackJack

Mal zum Vergleich:

Code: Alles auswählen

import string
from collections import Counter


def checkio(text):
    alphabet = set(string.ascii_lowercase)
    return Counter(c for c in text.lower() if c in alphabet).most_common(1)[0]
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

snafu hat geschrieben:@MagBen: Und das hat jetzt genau welchen Mehrwert im Vergleich zu der Zähler-Klasse, die Python schon in der Standardbibliothek mitbringt?
Du meinst

Code: Alles auswählen

from collections import Counter
print( Counter(text).most_common(3) )
Pro collections:
Der Numpy Code ist 4 Zeilen lang, der collections Code ist nur 2 Zeilen lang.
Beim Code mit Counter funktioniert Unicode auf Anhieb, wohingegen beim Numpy Beispiel das Beispiel erst noch umgeschrieben werden müsste.

Pro Numpy:
Der Beitrag enthielt lauffähigen Code.
Bei sehr großen Texten (>100 MB), wird der Numpy Code schneller sein.
a fool with a tool is still a fool, www.magben.de, YouTube
BlackJack

@MagBen: Schneller nützt ja erst einmal nichts wenn der Ansatz nicht mit Unicode umgehen kann. Und es war auch kein Histogram gefragt sondern der am meisten verwendete Buchstabe von a bis z, das heisst das müsste man da auch noch rein programmieren.

Ein weiterer Vorteil von `collections`: Im Gegensatz zu `numpy` ist das überall vorhanden. Zum Beispiel auch bei check.io.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

MagBen hat geschrieben:Pro Numpy:
Der Beitrag enthielt lauffähigen Code.
Bei sehr großen Texten (>100 MB), wird der Numpy Code schneller sein.
Letzteres trifft aber nur auf den Python-2-Zweig zu. Aktuelle Python-3-Interpreter haben den Code für den Counter seit längerem in C implementiert. Insofern müsste man da erstmal die Ausführungszeit messen, ob der Counter aus der Stdlib oder die Numpy-Variante für große Texte schneller ist. An sich ist Numpy ja auch eher weniger für die Verarbeitung von Zeichenketten gedacht. Und der von dir zuerst als Vorteil genannte Aspekt ist ja wohl nicht wirklich etwas Numpy-spezifisches.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Deutlich schneller, und Einzeiler:

Code: Alles auswählen

def checkio(text):
    return max(zip(map(text.lower().count, string.ascii_lowercase), string.ascii_lowercase))
bzw. wenn nur der Buchstabe gesucht wird:

Code: Alles auswählen

def checkio(text):
    return max(string.ascii_lowercase, key=text.lower().count)
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Sirius3 hat geschrieben:Deutlich schneller
Für jeden Buchstaben muss der komplette Text durchlaufen werden.
Sirius3 hat geschrieben:und Einzeiler
Mit import string ist es genauso ein Zweizeiler wie der collections Code.

Ansonsten ist der Code Klasse! Was für die Kniffel-Ecke: Was macht dieser Code? Dort findet man sonst eher C- und RegExp-Beispiele.
a fool with a tool is still a fool, www.magben.de, YouTube
Antworten