将文件中的句子转换为词汇列表

3 投票
3 回答
4073 浏览
提问于 2025-04-17 07:15

我正在使用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(),但我觉得在这种情况下,嵌套循环要简单得多。

撰写回答