我正在尝试使用gensim
进行主题建模。从我可以看到的模块文档来看,gensim
期望以列表形式接收其输入,列表中的每个项目都是文本:
documents = ["Human machine interface for lab abc computer applications",
"A survey of user opinion of computer system response time",
"The EPS user interface management system"]
我在目录中有一组文本要与gensim
一起使用,因此我需要将这些文件读入列表。这些文本中的每一个,其中一些由多行组成 - 文本的大小从不到100个单词到超过1000个单词 - 需要是列表中的一个项目。如果需要删除新行,我想我可以弄清楚如何做到这一点,但将它嵌入循环是我失败的地方......完全。 (事实上,我周末将自己带到了学校,但我经常把那部分搞得一团糟。)
我找到了各种有关如何将单个文件读入列表的有用信息 - 按行,按字或按任何方式 - 但我无法弄清楚如何读取一系列文本文件将一系列字符串全部包含在一个列表中 - 这是重要的一点:
textfile1.txt
textfile2.txt
需要成为
list = ['contents of textfile1', 'contents of textfile2']
这是我到目前为止所拥有的:
# get to the files, open an empty list
import glob
file_list = glob.glob('./texts' + '/*.txt')
documents = []
# Now to read the files into a list:
for file in file_list:
documents.append()
print documents
print documents
显然是一次性线,所以我可以查看我的工作,你可以看到我没有在循环中走得很远。
答案 0 :(得分:2)
with
不是循环。它只运行包含的代码一次。在此上下文中,它保证在with
块结束后,即使出现错误,也会关闭打开的文件。
查看目录中所有文本文件的一种方法是使用os.listdir()
:
import os
documents = []
for f in os.listdir():
if f[-4:] == '.txt':
documents.append(f[:-4])
或者理解:
documents = [f[:-4] for f in os.listdir() if f[-4:] == '.txt']
然后,您将拥有一个名为list
的{{1}},其中包含(当前工作)目录中文件的名称。例如,包含文件documents
和hello.txt
的文件夹将导致world.txt
包含字符串documents
和'hello'
。
请记住,完成后,您需要打开文件。建议使用'world'
结构。
with
这将导致contents = []
for document in documents:
with open(document+'.txt', 'r') as f:
contents.append(f)
list
。每个元素都是一个contents
对象,可以逐行迭代或以其他方式处理(如file
,用含有文件内容的字符串替换contents[0] = contents[0].read()
对象)。由于file
构造而无法理解这一点。
要回答您编辑过的问题(看起来比原版更合理),您可以按如下方式创建每个文件夹文本文件的with
字符串内容:
list
假设当前工作目录中的目录import glob
file_list = glob.glob('./texts' + '/*.txt')
# create document list:
documents = []
for filename in file_list:
with open(filename, 'r') as f:
documents.append(f.read()) # option 1, to get a direct string
# documents.append(f.readlines()) # option 2, to get a list of lines
# documents.append([item.strip() for item in f.readlines()]) # option 3, to get a list of lines with no linefeeds
# documents.append(f.read().replace('\n', ' ') # option 4, to get a direct string, linefeeds replaced with spaces
文件texts
包含first.txt
且文件'hello\nworld'
包含second.txt
,则这四个选项中的每一个都会创建'hi\npeople'
的不同结果,表示如下(每个语句将使documents
等效于其相应的选项):
list
documents = ['hello\nworld', 'hi\npeople']
documents = [['hello\n', 'world'], ['hi\n', 'people']]
documents = [['hello', 'world'], ['hi', 'people']]
答案 1 :(得分:2)
首先,你显然不知道要放在with open...
中的内容。那么,你要打开的是每个*.txt
文件。你已经在循环中得到了每个file_path
。因此,您必须在循环内移动with open
以打开每个文件。 (正如TigerhawkT3所解释的那样,with
并不是一个循环,确保文件完全关闭。)
接下来,您需要做一些事情来读取每个文件。你说你已经知道如何以你想要的方式阅读单个文件,所以我不会解释它,我只会使用最简单的东西(文件本身,这是一个可迭代的行,新线仍在上线。
最后,您希望将所有列表连接成一个大的平面列表。您已经几乎使用documents.append
获得了该信息,但您希望此处extend
。 append
用于向列表添加一个元素; extend
用于添加来自另一个可迭代的所有元素。
所以,把它放在一起:
import glob
file_list = glob.glob('./texts' + '/*.txt')
documents = []
for file_path in file_list:
with open(file_path) as f:
documents.extend(f)
print documents
虽然这是你最初要求的,但它显然不是你想要的。您希望每个文件的内容都是一个巨大的字符串。这同样容易。 f.read()
将文件的内容读作一个巨大的字符串。当然现在你需要append
而不是extend
,因为你只需添加一个新东西而不是它们的列表。所以:
import glob
file_list = glob.glob('./texts' + '/*.txt')
documents = []
for file_path in file_list:
with open(file_path) as f:
documents.append(f.read())
print documents
真的,一旦你知道如何以你想要的任何格式读取单个文件(一个大字符串,每行的字符串列表,每行的行列表,它们本身就是单词或CSV列的列表,...... ),对多个文件执行相同操作只是将该代码包含在一个循环中,该循环将结果存储为list.append
或list.extend
(或者,最糟糕的是,类似dict[key]=value
或dict.setdefault(key, []).append(value)
)。这一切都很简单。