虽然像 @Michael 建议的那样使用来自于 collections
库的 Counter
更好,但我添加这个答案只是为了改进你的代码。(我相信这会成为一个新的Python学习者的好答案。)
从你代码中的注释中看来,你想要改进你的代码。而且我认为你能够以单词形式读取文件内容(尽管通常我避免使用 read()
函数和类似 for line in file_descriptor:
这样的代码)。
由于 words
是一个字符串,在 for 循环中,for i in words:
循环变量 i
不是一个单词而是一个字符。你正在迭代字符串中的字符,而不是迭代字符串中的单词。为了理解这一点,请注意以下代码片段:
>>> for i in "Hi, h r u?":
... print i
...
H
i
,
h
r
u
?
>>>
因为逐个字符地迭代给定的字符串而不是逐个单词地迭代并不是您希望实现的功能,要逐个单词地迭代,您应该在Python的字符串类中使用split
方法/函数来实现。
str.split(str="", num=string.count(str))
方法返回字符串中所有单词的列表,使用str作为分隔符(如果未指定,则拆分所有空格),可选限制拆分次数到num。
请注意下面的代码示例:
Split:
>>> "Hi, how are you?".split()
['Hi,', 'how', 'are', 'you?']
使用split的循环:
>>> for i in "Hi, how are you?".split():
... print i
...
Hi,
how
are
you?
看起来你需要的东西很不错。但是除了单词“Hi,”之外,因为split()默认会以空格拆分,所以“Hi,”会被保留为一个字符串(显然),而你不希望出现这种情况。
要计算文件中单词的频率,一个好的解决方案是使用正则表达式。但首先,为了保持答案简单,我将使用replace()方法。该方法str.replace(old, new[, max])
返回字符串的副本,其中old的出现已被替换为new,并可选择将替换次数限制为max。
现在请查看下面的代码示例,看看我提出了什么建议:
>>> "Hi, how are you?".split()
['Hi,', 'how', 'are', 'you?']
>>> "Hi, how are you?".replace(',', ' ').split()
['Hi', 'how', 'are', 'you?']
循环:
>>> for word in "Hi, how are you?".replace(',', ' ').split():
... print word
...
Hi
how
are
you?
现在,如何计算频率:
一种方法是像@Michael建议的那样使用Counter
,但你可以采用从空字典开始的方法来实现。请参考下面的代码示例:
words = f.read()
wordfreq = {}
for word in .replace(', ',' ').split():
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
因为最开始的时候
wordfreq
为空,所以你不能直接把它赋值给
wordfreq[word]
,否则会出现键异常错误。所以我使用了
setdefault
字典方法。
dict.setdefault(key, default=None)
与
get()
类似,但如果键不在字典中,它将设置
dict[key]=default
。因此,当一个新单词第一次出现时,我使用
setdefault
将其设置为
0
,然后将其加上
1
并赋值到同一个字典中。
我已经编写了一个等效的代码,使用
with open代替单个
open
。
with open('~/Desktop/file') as f:
words = f.read()
wordfreq = {}
for word in words.replace(',', ' ').split():
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
print wordfreq
那是这样运行的:
$ cat file
this is the textfile, and it is used to take words and count
$ python work.py
{'and': 2, 'count': 1, 'used': 1, 'this': 1, 'is': 2,
'it': 1, 'to': 1, 'take': 1, 'words': 1,
'the': 1, 'textfile': 1}
使用re.split(pattern, string, maxsplit=0, flags=0)
只需要更改for循环:for i in re.split(r"[,\s]+", words):
,即可生成正确的输出。
编辑:最好查找所有字母数字字符,因为可能有多个标点符号。
>>> re.findall(r'[\w]+', words)
['this', 'is', 'the', 'textfile', 'and',
'it', 'is', 'used', 'to', 'take', 'words', 'and', 'count']
使用for循环的方式如下:for word in re.findall(r'[\w]+', words):
如果不使用read()
,应该怎么编写代码:
文件内容为:
$ cat file
This is the text file, and it is used to take words and count. And multiple
Lines can be present in this file.
It is also possible that Same words repeated in with capital letters.
代码是:
$ cat work.py
import re
wordfreq = {}
with open('file') as f:
for line in f:
for word in re.findall(r'[\w]+', line.lower()):
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
print wordfreq
使用lower()
将大写字母转换为小写字母。
输出:
$python work.py
{'and': 3, 'letters': 1, 'text': 1, 'is': 3,
'it': 2, 'file': 2, 'in': 2, 'also': 1, 'same': 1,
'to': 1, 'take': 1, 'capital': 1, 'be': 1, 'used': 1,
'multiple': 1, 'that': 1, 'possible': 1, 'repeated': 1,
'words': 2, 'with': 1, 'present': 1, 'count': 1, 'this': 2,
'lines': 1, 'can': 1, 'the': 1}