簡體   English   中英

獲取字符串最大出現的第一個字母

[英]Get first letter with maximum occurence of a string

我想得到一個字符串最大出現的第一個字母。

例如:

 "google" -> g  
 "azerty" -> a  
 "bbbaaa" -> b

我已經有一個工作代碼,使用OrdererDict()來避免自動密鑰重新排列

from collections import OrderedDict

sentence = "google"

d = OrderedDict()

for letter in sentence:
    if letter not in d.keys():
        d[letter] = sentence.count(letter)

print(max(d, key=d.get)) # g

但我正在尋找一種可能的單線或更優雅的解決方案(如果可能的話)。

注意:我已經嘗試使用Counter()但它不起作用,因為python中的dict不記得鍵插入的順序。

例如

from collections import Counter

sentence = "bbbaaa"

c = Counter(sentence)
print(c.most_common()[0][0]) # have 50% chances of printing 'a' rather than 'b'.

獎金問題:有人能解釋為什么OrderedDict()不是python中的默認字典行為嗎?

collections.OrderedDict的文檔實際上有一個OrderedCounter的配方

In [5]: from collections import Counter, OrderedDict

In [6]: class OrderedCounter(Counter, OrderedDict):
   ...:     pass
   ...:

In [7]: OrderedCounter("google").most_common()[0][0]
Out[7]: 'g'

可能不是很快,但是單行!

>>> s = "aaabbbbc"
>>> sorted(s, key=lambda c: (-s.count(c), s.index(c)))[0]
'b'

編輯

甚至更短,感謝@Ohad Eytan的評論:

>>> min(s, key=lambda c: (-s.count(c), s.index(c)))
'b'

基准

今晚覺得無聊,所以我基准測試(使用timeit )測試@Joohwan的most_common_char()解決方案(mostcc),@ Blender的OrderedCounter解決方案(odict)和我自己的一個線性解決方案(onelin,使用min變體)。 最快的解決方案始終是mostcc:對於包含少量不同字符的長字符串,比onelin快~10倍,對於非常短的字符串,比odict快4倍。 對於具有少量重復字符的短字符串或字符串,onelin擊敗odict(否則,它是相反的)。 以下是詳細信息(長度=字符串的長度,#chars =從每個字符中隨機選擇的不同unicode字符的數量,mostcc =執行10,000次mostcc的時間,odict =與mostcc相比多長的odict,onelin =與大多數人相比,線上多久了。

Length  #chars  mostcc odict  onelin
10      10:     0.08s  3.76x  1.61x
10      100:    0.10s  3.57x  1.27x
10      1000:   0.12s  3.12x  1.34x
100     10:     0.43s  1.96x  3.29x
100     100:    0.59s  2.16x  2.18x
100     1000:   0.80s  1.92x  1.72x
1000    10:     3.48s  1.56x  9.79x
1000    100:    3.44s  1.72x  6.43x
1000    1000:   6.55s  1.68x  3.30x

我知道你想要一個單行,但是如果你不得不多次重復這個任務或者處理很長的句子怎么辦? 我不知道這里的確切用例,但考慮到算法的空間和時間復雜性,您可能值得花些時間。

例如,在您的解決方案中,您使用sentence.count()迭代句子多次,這需要O(n * number of unique characters) 之后,再次遍歷ordereddict以查找max(另一個O(number of unique characters)操作)。

在公認的解決方案中,我們最終必須定義一個新類(它打破了你的1個班輪要求btw)並實例化新對象,其中包含很多樣板代碼和功能,你可能不需要每次執行任務。

如果你不介意再多行代碼(再次,我知道這不是問題所在),我們可以構建一個可重用的函數,它只需迭代字符串一次並使用常量和最小的空間:

from collections import defaultdict


def most_common_char(sentence):
    if not sentence:
        return ''

    max_count = 1
    max_char = sentence[-1]
    char_counts = defaultdict(int)
    char_counts[max_char] = 1

    for i in xrange(len(sentence) - 2, -1, -1):
        char = sentence[i]
        char_counts[char] += 1
        if char_counts[char] >= max_count:
            max_count = char_counts[char]
            max_char = char

    return max_char

我們瀏覽字符串時,我們會跟蹤具有最大計數的字符,並在迭代結束時將其吐出。 請注意,我們向后迭代,因為您需要首先出現的字母(即最后更新的勝利)。

您可以將Counter()next() Counter()一起使用來查找滿足條件的第一個字母:

>>> s = "google"
>>> c = Counter(s)
>>> next(x for x in s if c[x] == c.most_common(1)[0][1])
'g'

您還可以通過將結果列表按各種屬性排序來修復您在問題結尾處描述的有關使用Counter的問題:首先計算,其次是字典順序,如下所示:

from collections import Counter

sentence = "google"

c = Counter(sentence)
print(sorted(c.most_common(), key = lambda x: (-x[1], sentence.index(x[0]))))

輸出:

=> [('g', 2), ('o', 2), ('l', 1), ('e', 1)]

純娛樂:

高爾夫版本

# If your sentence is s:
print(sorted(collections.Counter(s).most_common(),key=lambda x:(-x[1],s.index(x[0]))))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM