查找词频 - 无需计数器
我正在学习Python 3.3,使用的网站是 http://GrokLearning.com
我的目标是写一个单词计数程序,这个程序可以从用户那里读取多行纯文本,然后打印出每个不同的单词,并统计每个单词出现的次数。所有输入的单词都将是小写字母,不包含标点符号或数字。输出的单词列表将按字母顺序排列。
这个程序不允许使用Counter或Collections模块。当我提交使用Counter的解决方案时,编辑器会假装Counter的代码不存在。
这是我目前的代码:
all = []
count = {}
line = input("Enter line: ")
while line:
word = line.split()
line = input("Enter line: ")
for w in word:
count[w] = word.count(w)
for word in sorted(count):
print(word, count[word])
我代码的问题是:如果一个单词在多行中重复出现,代码只会统计这个单词在最后一行出现的次数(而不是总次数)。
> this is another test test
> test test test test test
> test test test
>
another 1
is 1
test 3
this 1
我知道我没有利用我的列表“all”。我尝试过用all.append(word)来制作一个包含用户输入的所有单词的列表,但我的代码统计的次数是0(可能是因为最后一行需要为空才能结束while循环?)
作为参考,我已经浏览了所有免费的模块,但没有使用任何付费的模块。请原谅我:由于我的知识有限,请用简单的术语解释你的答案。
4 个回答
在你的 for
循环中,你可以这样做:
if w in count:
count[w] += word.count(w) # word already in dictionary, update the count
else:
count[w] = word.count(w) # word not in dictionary, add count for first time
最简单的修复方法和最快的代码:
for w in word:
count[w] = count.get(w, 0) + 1
get
方法会返回和某个键(key)相关联的值,如果这个键不存在的话,就返回第二个可选参数的值。(如果没有指定第二个参数,并且这个键还没有定义,那么会返回 None
)。所以对于所有从未出现过的单词,默认计数是 0
。然后对于每个遇到的单词,计数会设置为之前的计数加 1。
试着在纸上跟着你程序的逻辑走一遍,看看有什么问题。
- 用户输入多行文本
- 逐行处理每一行
- 在当前这一行中,计算“word”出现的次数
- 然后移动到下一行
- 处理找到的单词
- 打印出单词和它的出现频率
所以每次读取一行时,你都在把计数器设置为新的值,而没有考虑之前的行。
如果你在纸上解决这个“bug”,你会怎么做?然后你会如何把这种不同的逻辑应用到你的程序中呢?
问题出在这里:
for w in word:
count[w] = word.count(w)
在你的代码中,你并没有增加计数,而是每次遇到一个单词时都重置计数。举个例子,如果之前count['this']
的值是1,下次再遇到这个单词时,你又把计数设为1,而不是在原来的基础上加1。
第二个问题出在表达式word.count(w)
上。这个表达式是用来计算一个单词在一行中出现了多少次,而同时循环又是遍历每一个单词。这意味着如果你正确地更新(而不是重置)你的计数,你会计算得太多。
比如,如果这一行有三个'test',那么你更新计数时会变成3 x 3 = 9。
要解决这个问题,你需要处理两种情况:
- 如果一个单词已经在计数中(也就是说你之前见过这个单词),那么就把计数加1
- 如果这个单词不在计数中,说明这是你第一次见到它,就把计数设为1
这里有个建议:
for w in word:
if w in count:
count[w] += 1
else:
count[w] = 1