2010-11-09 40 views
9

Tôi đã tìm thấy vấn đề về lập trình này trong khi xem xét việc đăng bài trên SO. Tôi nghĩ nó khá thú vị và là một lập trình viên Python mới bắt đầu tôi đã cố gắng giải quyết nó. Tuy nhiên tôi cảm thấy giải pháp của tôi khá ... lộn xộn ... ai có thể đưa ra bất kỳ gợi ý nào để tối ưu hóa nó hay làm cho nó sạch hơn không? Tôi biết nó khá tầm thường, nhưng tôi đã vui vẻ viết nó. Lưu ý: Python 2.6Tìm ký tự thường xuyên nhất trong chuỗi

Vấn đề:

Viết pseudo-code (hoặc mã thực tế) cho một chức năng mà mất trong một chuỗi và trả về bức thư đó xuất hiện nhiều nhất trong chuỗi đó.

nỗ lực của tôi:

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

Output:

>>> 
('l', 3) 

Cập nhật Ví dụ:

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

Ghi chú ngẫu nhiên: bạn nên đọc [PEP 8] (http://www.python.org/dev/peps/pep-0008/), tài liệu đề xuất kiểu mã hóa Python được khuyến nghị. Các phương thức nên trong snake_case chứ không phải là mixedCase. –

+0

bản sao có thể có của [Cách tìm các phần tử phổ biến nhất trong danh sách?] (Http://stackoverflow.com/questions/3594514/how-to-find-most-common-elements-of-a-list) – kennytm

+0

có thể trùng lặp của [Python phần tử phổ biến nhất trong danh sách] (http://stackoverflow.com/questions/1518522/python-most-common-element-in-a-list) – nawfal

Trả lời

18

Có rất nhiều cách để làm ngắn này. Ví dụ, bạn có thể sử dụng lớp Counter (bằng Python 2.7 hoặc mới hơn):

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

Nếu bạn không có điều đó, bạn có thể thực hiện kiểm đếm bằng tay (2,5 hoặc sau đó có defaultdict):

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

Có nói rằng, không có gì quá khủng khiếp sai với việc triển khai của bạn.

+5

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

+0

@KennyTM: thực sự, cảm ơn! –

+1

Cảm ơn câu trả lời của bạn (bạn cũng vậy Chris Morgan), nhưng tôi đoán tôi quên đề cập rằng nếu nhiều nhân vật là thường xuyên nhất, tất cả chúng đều nên được xuất ra. (ví dụ: 'abcdefg' xuất ra a = 1, b = 1, v.v.) Tôi nghĩ đây là phần khó khăn nhất, do đó mớ hỗn độn ở cuối. Tôi đã chỉnh sửa câu hỏi. – Sunandmoon

0

Dưới đây là một vài điều tôi muốn làm:

  • Sử dụng collections.defaultdict thay vì dict bạn khởi bằng tay.
  • Sử dụng chức năng sắp xếp sẵn có và tối đa như max thay vì tự làm việc đó - dễ dàng hơn.

Dưới đây là kết quả cuối cùng của tôi:

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: 'letters' sẽ chính xác hơn là' letter', vì nó là một biến chứa chính xác một chữ cái. – EOL

+1

@EOL: true; Tôi đã không đổi tên biến đó từ những gì anh ta có - tôi tự đặt nó là 'char', tôi nghĩ, vì nó không chỉ là một lá thư ... –

3

Nếu bạn đang sử dụng Python 2.7, bạn có thể nhanh chóng thực hiện điều này bằng cách sử dụng các bộ sưu tập mô-đun. bộ sưu tập là mô-đun cấu trúc dữ liệu hiệu suất cao. Đọc thêm tại 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

Nếu bạn muốn có tất cả các nhân vật với số lượng tối đa số lượng, sau đó bạn có thể làm một biến thể của một trong hai ý tưởng đề xuất cho đến nay:

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) 

này sản lượng, ví dụ:

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

này làm việc với bất kỳ trình tự: từ ngữ, mà còn [ 'hello', 'xin chào' , 'bonjour'], chẳng hạn.

Cấu trúc heapq rất hiệu quả trong việc tìm kiếm các phần tử nhỏ nhất của chuỗi mà không cần phân loại hoàn toàn. Mặt khác, vì không có nhiều chữ cái trong bảng chữ cái, bạn có thể cũng chạy qua danh sách được sắp xếp của các số cho đến khi không tìm thấy số lượng tối đa nữa, mà không làm mất tốc độ nghiêm trọng.

1

Dưới đây là cách để tìm ra nhân vật phổ biến nhất sử dụng một cuốn từ điển

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 được một danh sách các hàng mà đếm ký tự như (character, count). Chúng tôi áp dụng tối đa cho các bộ dữ liệu bằng cách sử dụng count và trả lại số đó là character. Trong trường hợp hòa, giải pháp này sẽ chỉ chọn một.

-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

Cảm ơn bạn vì đoạn mã này, có thể cung cấp một số hạn chế, ngay lập tức Cứu giúp. Một lời giải thích thích hợp [sẽ cải thiện rất nhiều] (// meta.stackexchange.com/q/114762) giá trị lâu dài của nó bằng cách hiển thị * tại sao * đây là một giải pháp tốt cho vấn đề, và sẽ làm cho nó hữu ích hơn cho người đọc trong tương lai các câu hỏi tương tự khác. Vui lòng [sửa] câu trả lời của bạn để thêm một số giải thích, bao gồm các giả định bạn đã thực hiện. Cụ thể, 'Counter' đến từ đâu? –

+0

Số lượt truy cập phải được nhập bằng cách sử dụng lệnh 'từ bộ đếm nhập bộ sưu tập' –

+0

Vui lòng [sửa] câu trả lời của bạn để hiển thị thông tin bổ sung, thay vì viết nó làm nhận xét. Nhận xét có thể biến mất mà không có dấu vết, do đó, nó thực sự cần phải là một phần của câu trả lời của bạn. Cảm ơn bạn. –

Các vấn đề liên quan