我读了一个文本文件进行分析,每个单词都附加到一个列表中并给出一个id
#!/usr/bin/python3
with fi as myfile:
for line in myfile:
for item in line.split(' '):
db[0].append(id_+1)
db[2].append(item)
...more stuff
然后我通过列表搜索每个单词以查找其匹配项,并将计数存储为 sim1 。如果找到匹配项,我会测试下一个单词是否与连续单词匹配,并将其计数存储为 sim2 。同样适用于 sim3 。我的代码如下:
for i in range(id_-3):
sim1=0
sim2=0
sim3=0
for j in range(id_-3):
if i==j: continue;
if db[2][i] == db[2][j]:
sim1 += 1
if db[2][i+1] == db[2][j+1]:
sim2 += 1
if db[2][i+2] == db[2][j+2]:
sim3 += 1
db[3].append(sim1)
db[4].append(sim2)
db[5].append(sim3)
这样可行,但速度太慢了! 我相信python提供了更快的搜索方法,但我仍然是Py新手!
答案 0 :(得分:2)
算法的缓慢主要来自于这样一个事实,即你有一个内部循环,它迭代外部循环中包含的len(db [2])次,它也会迭代len(db [2])次。这意味着内部代码正在执行len(db [2])^ 2次。例如,如果您的文件很大并且您正在解析5000个单词,则代码运行5000 ^ 2 = 25,000,000次!
因此,解决问题的攻击角度是找到消除或显着降低内循环成本的方法。下面是一个示例解决方案,只需要遍历len(db [2])一次,然后执行第二个单独的循环,迭代一个更小的项集。在第二次迭代中有一些内部循环,但它们运行的次数更少,并且几乎无关紧要。
我使用一个大约48kb的文本文件计算你的算法和我的算法。您的算法在我的计算机上平均大约14秒,我的算法平均为0.6秒。因此,通过取消内部循环,算法现在快了23倍。我还进行了一些其他的小优化,例如将比较更改为数字而不是文本,并从头开始创建完整大小的存储阵列,以避免使用append()。 Append()使解释器根据需要动态增加数组的大小,这比较慢。
from collections import defaultdict
# Create zero-filled sim1, sim2, sim3 arrays to avoid append() overhead
len_ = len(db[2]) - 2
for _ in range(3):
db.append([0] * len_)
# Create dictionary, containing d['word'] = [count, [indexes]]
# Do just one full iteration, and make good use of it by calculating
# sim1 (as 'count') and storing an array of number indexes for each word,
# allowing for a very efficient loop coming up...
d = defaultdict(lambda: [0, []])
for index, word in enumerate(db[2]):
if index < len_:
# Accumulate sim1
d[word][0] += 1
# Store all db[2] indexes where this word exists
d[word][1].append(index)
# Now loop only through words which occur more than once (smaller loop)
for word, (count, indexes) in d.iteritems():
if count > 1:
# Place the sim1 values into the db[3] array
for i in indexes:
if i < len_:
db[3][i] = count - 1
# Look for sim2 matches by using index numbers
next_word = db[2][i+1]
for next_word_index in d[next_word][1]:
if next_word_index - 1 != i and next_word_index - 1 in indexes:
# Accumulate sim2 value in db[4]
db[4][i] += 1
# Look for sim3 matches
third_word = db[2][i+2]
if third_word == db[2][next_word_index + 1]:
# Accumulate sim3 value in db[5]
db[5][i] += 1
答案 1 :(得分:-2)
是的,你正在进行字符串比较。那真的很慢。 你想要的是将你的字符串编译为常规模式。 :)
从python中查看库