将文件中的句子转换为词汇列表
我正在使用Python把文本文件中的句子里的单词转换成一个个小的单元(也就是“token”),然后放到一个列表里,以便统计每个单词出现的频率。不过,我在把不同的句子合并成一个列表时遇到了问题。以下是我做的:
f = open('music.txt', 'r')
sent = [word.lower().split() for word in f]
这样我得到了下面这个列表:
[['party', 'rock', 'is', 'in', 'the', 'house', 'tonight'],
['everybody', 'just', 'have', 'a', 'good', 'time'],...]
因为文件中的句子是分开写在不同的行里的,所以它返回的是一个列表的列表,而defaultdict无法识别这些单独的单元来进行计数。
我尝试了下面这个列表推导式,想把不同列表中的单元提取出来,合并成一个单一的列表,但结果却是一个空列表:
sent2 = [[w for w in word] for word in sent]
有没有办法用列表推导式来做到这一点?或者有没有更简单的方法?
3 个回答
0
列表推导式可以完成这个任务,但它会把所有东西都放在内存里。对于很大的输入,这可能会造成很大的负担。下面的解决方案即使在处理大文件时,也不会在内存中积累大量数据。最终的结果是一个字典,格式是 {token: occurrences}
。
import itertools
def distinct_tokens(filename):
tokendict = {}
f = open(filename, 'r')
tokens = itertools.imap(lambda L: iter(L.lower.split()), f)
for tok in itertools.chain.from_iterable(tokens):
if tok in tokendict:
tokendict[tok] += 1
else:
tokendict[tok] = 1
f.close()
return tokendict
1
只需将整个文件一次性读入内存,作为一个完整的字符串,然后对这个字符串使用一次 split
方法就可以了。在这种情况下,不需要逐行读取文件。
所以你的核心代码可以简短到:
sent = open("music.txt").read().split()
(当然,像关闭文件、检查错误这些小细节会让代码稍微变长一些)
因为你想要统计单词的频率,可以使用 collections.Counter 类来实现:
from collections import Counter
counter = Counter()
for word in open("music.txt").read().split():
counter[word] += 1
5
只需在列表推导式中使用一个嵌套循环:
sent = [word for line in f for word in line.lower().split()]
还有一些其他的方法可以做到这一点,比如使用 itertools.chain.from_iterable()
,但我觉得在这种情况下,嵌套循环要简单得多。