您将覆盖lst
的值。您将它作为函数的参数(在这种情况下,它是一个字符串列表)和文件中的单词列表(在这种情况下,它是一个字符串列表的列表)。当你这样做:
if lst[i][j] in lst
比较总是返回False
因为lst[i][j]
是str
,但lst
包含字符串只列出,而不是字符串本身。这意味着dic
的分配不会执行,因此会得到一个空的dict
。
为了避免这种情况,你应该为你存储词列表使用不同的名称,例如:
In [4]: !echo 'a b c\nd e f' > test.txt
In [5]: def index(filename, lst):
...: infile = open(filename, 'r')
...: lines = infile.readlines()
...: words = []
...: dic = {}
...: for line in lines:
...: line_words = line.split()
...: words.append(line_words)
...: for i in range(len(words)):
...: for j in range(len(words[i])):
...: if words[i][j] in lst:
...: dic[words[i][j]] = i
...: return dic
...:
In [6]: index('test.txt', ['a', 'b', 'c'])
Out[6]: {'a': 0, 'c': 0, 'b': 0}
也有很多的事情可以发生改变。
当你想迭代一个列表时,你不必显式地使用索引。如果你需要的指数,你可以使用enumerate
:
for i, line_words in enumerate(words):
for word in line_words:
if word in lst: dict[word] = i
您也可以直接迭代上的一个文件(参阅更多的信息蟒蛇教程Reading and Writing Files部分):
# use the with statement to make sure that the file gets closed
with open('test.txt') as infile:
for i, line in enumerate(infile):
print('Line {}: {}'.format(i, line))
事实上我不明白你为什么会先建立那个words
列表。只是itertate直接在构建字典文件:
def index(filename, lst):
with open(filename, 'r') as infile:
dic = {}
for i, line in enumerate(infile):
for word in line.split():
if word in lst:
dic[word] = i
return dic
你dic
值应该名单,因为多行包含相同的字。因为它代表你dic
只会保存最后一行,其中一个字发现:
from collections import defaultdict
def index(filename, words):
# make faster the in check afterwards
words = frozenset(words)
with open(filename) as infile:
dic = defaultdict(list)
for i, line in enumerate(infile):
for word in line.split():
if word in words:
dic[word].append(i)
return dic
如果你不想使用collections.defaultdict
可以用dic = {}
替代dic = defaultdict(list)
,然后改变:
dic[word].append(i)
有了:
if word in dic:
dic[word] = [i]
else:
dic[word].append(i)
,或者,你可以使用dict.setdefault
:
dic.setdefault(word, []).append(i)
虽然这最后一种方式比原始代码慢一点。
请注意,所有这些解决方案的属性,如果在文件中找不到一个单词它根本不会出现在结果中。但是,您可能希望在结果中使用emty列表作为值。在这种情况下,它更简单的dict
以空列表开始循环,如以前:
dic = {word : [] for word in words}
for i, line in enumerate(infile):
for word in line.split():
if word in words:
dic[word].append(i)
参考文档中关于List Comprehensions和Dictionaries,了解第一线。然而
dic = {word : [] for word in words}
for i, line in enumerate(infile):
for word in words:
if word in line.split():
dic[word].append(i)
注意,这将是慢,因为:
您还可以重复words
的替代线路,这样
line.split()
返回一个列表,所以word in line.split()
会必须扫描所有列表。
- 您正在重复计算
line.split()
。
您可以尝试解决这两个问题做:
dic = {word : [] for word in words}
for i, line in enumerate(infile):
line_words = frozenset(line.split())
for word in words:
if word in line_words:
dic[word].append(i)
请注意,在这里我们在line.split()
一次迭代打造集也超过words
。根据两组的大小,这可能比原始版本更慢或更快(迭代超过line.split()
)。
但是在这一点上,它可能更快地相交集:
dic = {word : [] for word in words}
for i, line in enumerate(infile):
line_words = frozenset(line.split())
for word in words & line_words: # & stands for set intersection
dic[word].append(i)
您将在'lst = []'行中将'[]'重新赋值给给定的参数'lst'。这只是一个错字。 – soon
说实话,这个逻辑在很多方面都是错误的。我建议你首先重新审视你试图实现的算法。 – NPE