2010-11-09 31 views
9

Ich habe dieses Programmierproblem beim Betrachten einer Stellenausschreibung auf SO gefunden. Ich fand es sehr interessant und als Anfänger Python Programmierer habe ich versucht, es anzugehen. Ich denke jedoch, dass meine Lösung ziemlich ... unordentlich ist ... kann jemand irgendwelche Vorschläge machen, um es zu optimieren oder es sauberer zu machen? Ich weiß, es ist ziemlich trivial, aber ich hatte Spaß beim Schreiben. Hinweis: Python 2.6Das häufigste Zeichen in einer Zeichenfolge finden

Das Problem:

schreiben Pseudo-Code (oder tatsächlichen Code) für eine Funktion, die in einem String nimmt und die Buchstaben, die in dieser Zeichenfolge erscheint.

Mein Versuch:

import string 

def find_max_letter_count(word): 

    alphabet = string.ascii_lowercase 
    dictionary = {} 

    for letters in alphabet: 
     dictionary[letters] = 0 

    for letters in word: 
     dictionary[letters] += 1 

    dictionary = sorted(dictionary.items(), 
         reverse=True, 
         key=lambda x: x[1]) 

    for position in range(0, 26): 
     print dictionary[position] 
     if position != len(dictionary) - 1: 
      if dictionary[position + 1][1] < dictionary[position][1]: 
       break 

find_max_letter_count("helloworld") 

Ausgang:

>>> 
('l', 3) 

Aktualisiert Beispiel:

find_max_letter_count("balloon") 
>>> 
('l', 2) 
('o', 2) 
+0

Hintergrund Hinweis: Sie sollten [PEP 8] (http://www.python.org/dev/peps/pep-0008/) lesen, die die empfohlene Python Codierung Stil dokumentiert. Methoden sollten in snake_case anstatt in mixedCase sein. –

+0

möglich duplicate of [Wie finde ich die häufigsten Elemente einer Liste?] (Http://stackoverflow.com/questions/3594514/how-to-find-most-common-elements-of-a-list) – kennytm

+0

möglich duplizieren von [Pythons häufigstem Element in einer Liste] (http://stackoverflow.com/questions/1518522/python-fast-common-element-in-a-list) – nawfal

Antwort

18

Es gibt viele Möglichkeiten, diese kürzer zu tun. Zum Beispiel können Sie die Counter Klasse (in Python 2.7 oder höher) verwenden:

import collections 
s = "helloworld" 
print(collections.Counter(s).most_common(1)[0]) 

Wenn Sie das nicht haben, können Sie die tally manuell tun können (2.5 oder höher haben defaultdict):

d = collections.defaultdict(int) 
for c in s: 
    d[c] += 1 
print(sorted(d.items(), key=lambda x: x[1], reverse=True)[0]) 

Nichtsdestotrotz gibt es nichts allzu falsches mit Ihrer Implementierung.

+5

['.most_common()'] (http://docs.python.org/py3k/library/collections.html#collections.Counter.most_common) .... – kennytm

+0

@KennyTM: In der Tat, danke! –

+1

Danke für Ihre Antwort (Sie auch Chris Morgan), aber ich denke, ich vergaß zu erwähnen, dass, wenn mehrere Zeichen am häufigsten sind, sie alle ausgegeben werden sollten. (z. B. 'abcdefg' gibt a = 1, b = 1, usw. aus) Ich dachte, das sei der heikelste Teil, daher das Chaos am Ende. Ich habe die Frage bearbeitet. – Sunandmoon

0

Hier sind ein paar Dinge, die ich tun würde:

  • Verwenden collections.defaultdict anstelle des dict Sie manuell initialisieren.
  • Verwenden Sie eingebaute Sortier- und Max-Funktionen wie max anstatt es selbst auszuarbeiten - es ist einfacher.

Hier ist mein Endergebnis:

from collections import defaultdict 

def find_max_letter_count(word): 
    matches = defaultdict(int) # makes the default value 0 

    for char in word: 
     matches[char] += 1 

    return max(matches.iteritems(), key=lambda x: x[1]) 

find_max_letter_count('helloworld') == ('l', 3) 
+0

Nitpicking: "Buchstaben" wäre korrekter als "Buchstabe", da es eine Variable ist, die genau einen Buchstaben enthält. – EOL

+1

@EOL: wahr; Ich habe diese Variable nicht von dem, was er hatte, umbenannt - ich würde es selbst als "char" bezeichnen, denke ich, da es nicht nur ein Buchstabe ist ... –

3

Wenn Sie Python verwenden 2.7, können Sie dies tun, indem Sammlungen Modul. Sammlungen ist ein High-Performance-Datenstrukturen-Modul. Lesen Sie mehr bei http://docs.python.org/library/collections.html#counter-objects

>>> from collections import Counter 
>>> x = Counter("balloon") 
>>> x 
Counter({'o': 2, 'a': 1, 'b': 1, 'l': 2, 'n': 1}) 
>>> x['o'] 
2 
1

Wenn Sie alle die Zeichen mit der maximalen Anzahl von Zählungen haben wollen, dann können Sie auf einer der beiden Ideen eine Variation tun bisher vorgeschlagen:

import heapq # Helps finding the n largest counts 
import collections 

def find_max_counts(sequence): 
    """ 
    Returns an iterator that produces the (element, count)s with the 
    highest number of occurrences in the given sequence. 

    In addition, the elements are sorted. 
    """ 

    if len(sequence) == 0: 
     raise StopIteration 

    counter = collections.defaultdict(int) 
    for elmt in sequence: 
     counter[elmt] += 1 

    counts_heap = [ 
     (-count, elmt) # The largest elmt counts are the smallest elmts 
     for (elmt, count) in counter.iteritems()] 

    heapq.heapify(counts_heap) 

    highest_count = counts_heap[0][0] 

    while True: 

     try: 
      (opp_count, elmt) = heapq.heappop(counts_heap) 
     except IndexError: 
      raise StopIteration 

     if opp_count != highest_count: 
      raise StopIteration 

     yield (elmt, -opp_count) 

for (letter, count) in find_max_counts('balloon'): 
    print (letter, count) 

for (word, count) in find_max_counts(['he', 'lkj', 'he', 'll', 'll']): 
    print (word, count) 

Dies ergibt zum Beispiel:

[email protected] /tmp % python count.py 
('l', 2) 
('o', 2) 
('he', 2) 
('ll', 2) 

Dieses mit beliebiger Reihenfolge funktioniert: Worte, sondern auch [ 'Hallo', 'Hallo' "Bonjour" zum Beispiel.

Die heapq Struktur ist sehr effizient bei der Suche nach den kleinsten Elementen einer Sequenz, ohne sie vollständig zu sortieren. Auf der anderen Seite, da es nicht so viele Buchstaben im Alphabet gibt, können Sie wahrscheinlich auch die sortierte Liste der Zählungen durchlaufen, bis die maximale Anzahl nicht mehr gefunden wird, ohne dass dies zu einem ernsthaften Geschwindigkeitsverlust führt.

1

Hier ist die Art und Weise häufigste Zeichen mit einem Wörterbuch

message = "hello world" 
d = {} 
letters = set(message) 
for l in letters: 
    d[message.count(l)] = l 

print d[d.keys()[-1]], d.keys()[-1] 
0
def most_frequent(text): 
    frequencies = [(c, text.count(c)) for c in set(text)] 
    return max(frequencies, key=lambda x: x[1])[0] 

s = 'ABBCCCDDDD' 
print(most_frequent(s)) 

frequencies ist eine Liste von Tupeln zu finden, die die Zeichen als (character, count) zählen. Wir wenden max auf die Tupel an, indem wir count verwenden und die character des Tupels zurückgeben. Im Falle eines Unentschiedens wird diese Lösung nur einen auswählen.

-1
#file:filename 
#quant:no of frequent words you want 

def frequent_letters(file,quant): 
    file = open(file) 
    file = file.read() 
    cnt = Counter 
    op = cnt(file).most_common(quant) 
    return op 
+0

Danke für dieses Code-Snippet, das einige begrenzte, sofortige liefern könnte Hilfe. Eine angemessene Erklärung [würde erheblich verbessern] (// meta.stackexchange.com/q/114762) ist ihr langfristiger Wert, indem sie zeigt * warum * das ist eine gute Lösung für das Problem, und würde es für zukünftige Leser mit mehr nützlich machen andere, ähnliche Fragen. Bitte [bearbeiten] Sie Ihre Antwort, um einige Erklärungen hinzuzufügen, einschließlich der Annahmen, die Sie getroffen haben. Wo kam 'Counter' konkret her? –

+0

Counter muss importiert werden, indem Sie den Befehl 'from collections import Counter' verwenden. –

+0

Bitte bearbeiten Sie Ihre Antwort, um die zusätzlichen Informationen anzuzeigen, anstatt sie als Kommentar zu schreiben. Kommentare können spurlos verschwinden, also muss es wirklich Teil Ihrer Antwort sein. Vielen Dank. –

Verwandte Themen