查找词频 - 无需计数器

3 投票
4 回答
3781 浏览
提问于 2025-04-18 07:43

我正在学习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 个回答

1

在你的 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
2

最简单的修复方法和最快的代码:

for w in word:
    count[w] = count.get(w, 0) + 1

get 方法会返回和某个键(key)相关联的值,如果这个键不存在的话,就返回第二个可选参数的值。(如果没有指定第二个参数,并且这个键还没有定义,那么会返回 None)。所以对于所有从未出现过的单词,默认计数是 0。然后对于每个遇到的单词,计数会设置为之前的计数加 1。

2

试着在纸上跟着你程序的逻辑走一遍,看看有什么问题。

  • 用户输入多行文本
  • 逐行处理每一行
    • 当前这一行中,计算“word”出现的次数
    • 然后移动到下一行
  • 处理找到的单词
    • 打印出单词和它的出现频率

所以每次读取一行时,你都在把计数器设置为新的值,而没有考虑之前的行。

如果你在纸上解决这个“bug”,你会怎么做?然后你会如何把这种不同的逻辑应用到你的程序中呢?

3

问题出在这里:

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

撰写回答