您將覆蓋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