这是一个简单的 Python 版本,使用defaultdict()
. 由于您说这是针对课程的,因此这并不是您要求的最终解决方案。
from collections import defaultdict
from operator import itemgetter
d = defaultdict(int)
name = raw_input("Enter file name: ")
with open(name, "r") as f:
for line in f:
for ch in line:
if ch.isalpha():
d[ch] += 1
lst = d.items()
# sort twice: once for alphabetical order, then for frequency (descending).
# Because the Python sort is "stable", we will end up with descending
# frequency, but alphabetical order for any frequency values that are equal.
lst.sort(key=itemgetter(0))
lst.sort(key=itemgetter(1), reverse=True)
for key, value in lst:
print value, key,
当您对打开的文件执行 for 循环时,就像for line in f
这里一样,Python 将从输入文件中一次抓取一行。然后我们在输入行上一次循环一个字符。然后我们检查它是否是一个字母,如果是,我们增加该字母的频率计数。
这段代码有一个错误。您希望它计算所有字母的频率,就好像它们都是小写一样,但是此代码将保留一个大写计数和另一个小写计数。我相信您可以弄清楚如何修改它,以便计数仅用于小写。
一旦我们完成计数,我们使用.items()
方法函数来获取(key, value)
元组列表。例如:('h', 3)
是一个带有字典键字符h
及其值的元组,计数为 3。
现在我们要排序。我向你展示了 Python 可以做到的一个绝妙技巧:由于排序是“稳定”排序,如果我们进行多个排序,Python 不会干扰早期排序的结果,除非它必须这样做。这意味着如果我们首先按字母顺序排序,然后按频率计数,那么对于频率计数相等的所有情况,我们将在该频率内获得字母顺序。因此,由于a
、b
和c
都是相同的频率(它们每个出现一次),您会期望部分输出为:1 a 1 b 1 c
现在,我有点棘手,但这很好学。sort 函数可以接受一个key
控制排序的参数。 key
应该是一个返回用于排序的值的函数。由于我们有一个元组列表,我们需要一个可以获取元组的一部分并返回它的键函数。我们可以写两个函数:
def get_key(kv_tuple):
return kv_tuple[0]
def get_value(kv_tuple):
return kv_tuple[1]
但是 Python 有一个函数,operator.itemgetter()
我们可以使用它。如果我们告诉它我们想要获取元组中的哪个位置,它将为我们创建一个关键函数,它将为我们获取元组的一部分。
由于我们希望首先按最大值对频率进行排序,因此我们还在reverse=True
该.sort()
方法的参数中进行了设置。
最后,我们遍历键、值元组和打印的列表。
这段代码还有另一个问题。您的示例输出显示您希望每个字母都在列表中,如果字母不在输入中,则计数为 0。这只计算那里的东西。
所以,我建议你重新编写这段代码。不要使用 a defaultdict
,而是尝试使用普通的dict
,但有一个循环将每个字母a
设置z
为dict
0 的计数。
我还建议,在您拥有dict
包含您要计数的字母的普通代码后,您更改决定是否计数的代码。目前它使用.isalpha()
方法函数来决定是否计算一个字符;相反,您可以检查该字符是否in
是字典。然后,您可以使用此代码来计算标点符号或数字或任何类型的字符。