如何计算字符串中出现最频繁的字母?

5
class MyString:
    def __init__(self, myString):
        self.__myString = myString

    def countWord(self):
         count = len(self.__myString.split())
         return count

    def findMostFrequentChar(self):
        # ?

我需要实现findMostFrequenctChar函数。她给我们唯一的提示是需要创建两个列表,这就让我感到迷惑了。

以下是调用该函数的代码:

def main():
    aString = MyString("This is a super long long long string. Please help count me")
    print("There are", aString.countWord(), "words in the string.")

    count, letter = aString.findMostFrequentChar()
    print("The most frequent character is", letter, "which appeared", count, "times")

main()

如果不能使用collections.Counter,可以使用字典来计算每个字母的数量。放弃那个使用两个列表的想法。 - timgeb
所以,这是作业吗?这对于作业来说还可以,但请记住,良好的实践应该涉及缓存 - 如果您的字符串不会改变,那么预先计算此值并将其存储为对象属性一次是有意义的。否则,将此功能与类分离,并定义一个独立的函数来为您执行计算。 - cs95
6个回答

4
她给我们的唯一提示是需要制作两个列表。这就是我被难住的地方。
这似乎意味着您不能使用collections.Counter,甚至可能不允许使用字典。
如果我们可以假设字母定义为英文字母,则一个列表就足够了。在这种情况下,您可以创建一个包含26个项目的列表,所有项目都初始化为0。然后,您可以遍历字符串的字符,并针对英文字母的每个字母,递增列表中第n个项目的计数,其中n是字母在字母表中的索引。
创建一个由26个零组成的列表:
counts = [0] * 26

循环遍历输入字符串s的每个字符:
for c in s:

检查字符是否为字母:

if 'a' <= c.lower() <= 'z'

计算字母在字母表中的从0开始的索引,并增加计数:

index = ord(c.lower()) - ord('a')
counts[index] += 1

一旦你得到了计数,你可以找到具有最大值的索引(留给你作为练习),并使用 chr(index + ord('a')) 获取相应的字符。


3
你可以使用sorted
class String:
    def __init__(self, s):   
       self.s = s
    def findMostFrequentChar(self):
       return sorted([(a, self.s.count(a)) for a in self.s], key=lambda x:x[-1])[-1]

你找到了最常见的字符。但是计数丢失了。 - David Bern
@DavidBern,楼主说只需要实现findMostFrequenctChar函数。 - Ajax1234
1
通过实现这个函数并使用count, letter = aString.findMostFrequentChar()来调用它,测试将会失败。 - David Bern
为了保险起见,我已经实现了一个计数功能。 - Ajax1234

2
如果您想使用来自 collections 模块的 Counter
from collections import Counter

def findMostFrequentChar(self):
    d = Counter(self.__myString.replace(' ', '').lower())        
    return d.most_common()[0]

如果不能使用Counter
def findMostFrequentChar(self):
    d = {}

    for ch in self.__myString.replace(' ', '').lower():
        if ch in d:
            d[ch] += 1
        else:
            d[ch] = 1

    most_frequent = max(d, key=d.get)
    return most_frequent, d[most_frequent]

将所有内容整合在一起:
class MyString:
    def __init__(self, myString):
        self.__myString = myString

    def countWord(self):
         count = len(self.__myString.split())
         return count

    def findMostFrequentChar(self):        
        d = {}

        for ch in self.__myString.replace(' ', '').lower():
            if ch in d:
                d[ch] += 1
            else:
                d[ch] = 1
        most_frequent = max(d, key=d.get)
        return most_frequent, d[most_frequent]


def main():    
    aString = MyString("This is a super long long long string. Please help count me")
    print("There are", aString.countWord(), "words in the string.")

    letter, count = aString.findMostFrequentChar()
    print("The most frequent character is", letter, "which appeared", count, "times")

main()

1
我将向您展示如何使用字典在不导入任何模块的情况下获取常规字符串中最频繁的字母。您的任务是相应地调整您的类。
我假设如果两个或更多字母具有相同的最高频率,则它们中的任何一个都是有效结果。
>>> s = 'aabacbcd'
>>> counts = {}
>>> for c in s:
...     counts[c] = counts.get(c, 0) + 1
... 
>>> counts
{'a': 3, 'c': 2, 'b': 2, 'd': 1}
>>> max(counts, key=counts.get)
'a'

1
我会使用字典来存储计数。 但首先,我想去除所有的空格和其他符号,然后只保留a-z,我还希望将大写字母和小写字母视为相同。
当字典构建完成后,我会使用max函数。 max需要一个可迭代对象,因此我们将字典作为元组(key, val)的“列表”传递给它。我们需要告诉max如何确定我们要比较什么,为此,我们提供了一个lambda函数,该函数将元组中的第二个元素(val)作为key-arg
作为回报,max将返回具有最高val的元组。
class MyString:

    def __init__(self, myString):
        self.__myString = myString

    def countWord(self):
        count = len(self.__myString.split())
        return count

    def findMostFrequentChar(self):
        counter = {}
        # Instead of performing various modifications on the string
        # one can instead filter all the undesired chars.
        # new_string = self.__myString.replace(' ', '').lower()
        new_string = list(filter(lambda x: 'a' >= x <= 'z', self.__myString.lower()))
        for char in new_string:

            if char in counter:
                counter[char] += 1
            else:
                counter[char] = 1

        key, value = max(counter.items(), key=lambda x:x[1])
        return value, key


def main():
    aString = MyString("This is a super long long long string. Please help count me")
    print("There are", aString.countWord(), "words in the string.")

    count, letter = aString.findMostFrequentChar()
    print("The most frequent character is", letter, "which appeared", count, "times")

main()

这段代码当前无法运行,该如何让它运行? - AmbieGirl
文件 "C:/Users/abrooks3/Downloads/assignment9.py",第31行,在主函数中: count, letter = aString.findMostFrequentChar() 文件 "C:/Users/abrooks3/Downloads/assignment9.py",第21行,在查找最常用字符的函数中: key, value = max(counter.items(), key=lambda x:x[1]) 属性错误:'dict'对象没有属性'iteritems'
- AmbieGirl
你使用的是哪个版本的Python? 并且你调用了 iteritems() - David Bern
我有Idle 3.6.2。 - AmbieGirl
请使用items()进行测试,很抱歉iteritems()在Python3中已被删除。 - David Bern
请再看一下代码......我做了一个计算错误....计数器不应该被设置为0....也许1更合理。总是把0当作起点是个坏习惯 :) - David Bern

0

“两个列表”部分很烦人。然而,在Python中,一个实用的工具来计算可迭代对象的元素是collections.Counter

from collections import Counter

# ...
    def findMostFrequentChar(self):
        return Counter(self.__myString).most_common()[0][0]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接