Python 将自定义函数应用于大型列表需要很长时间
问题:Python 将自定义函数应用于大型列表需要很长时间,python,list,multiprocessing,difflib,Python,List,Multiprocessing,Difflib,问题: import random , string , itertools , difflib from functools import partial N = 10 random.seed(123) words = [''.join(random.choice(string.ascii_lowercase) for i in range(5)) for j in range(10)] 我有一个长度为48000的单词列表,我正在尝试将可能出现的4个相互最接近的单词(如果存在的话)分组。我正
import random , string , itertools , difflib
from functools import partial
N = 10
random.seed(123)
words = [''.join(random.choice(string.ascii_lowercase) for i in range(5)) for j in range(10)]
我有一个长度为48000的单词列表,我正在尝试将可能出现的4个相互最接近的单词(如果存在的话)分组。我正在从difflib
模块获取这方面的帮助
我有两种方法可以做到这一点。使用difflib.Get_close_matches()
获取4个最接近的匹配项,或者对单词列表进行笛卡尔乘积,并从乘积列表中获取每个元组的分数
我有一个适用于较小列表的代码,但是当列表的长度增加时(在我的例子中是48k),它需要花费大量的时间。我正在为这个问题寻找一个可扩展的解决方案
复制此类列表的代码:
import random , string , itertools , difflib
from functools import partial
N = 10
random.seed(123)
words = [''.join(random.choice(string.ascii_lowercase) for i in range(5)) for j in range(10)]
我的尝试:
import random , string , itertools , difflib
from functools import partial
N = 10
random.seed(123)
words = [''.join(random.choice(string.ascii_lowercase) for i in range(5)) for j in range(10)]
1:创建了一个函数,该函数在创建笛卡尔积后返回分数。发布这篇文章,我可以在第一个元素上分组,并按我的意愿取前n名
def fun(x) : return difflib.SequenceMatcher(None,*x).ratio()
products = list(itertools.product(words,words))
scores = list(map(fun,products))
2:直接提供最佳n(4)个匹配的函数
这也是预期的产出
这两种方法都适用于较小的列表,但随着列表大小的增加,这需要很长的时间。因此,我尝试采用多处理:
多处理尝试1:
import random , string , itertools , difflib
from functools import partial
N = 10
random.seed(123)
words = [''.join(random.choice(string.ascii_lowercase) for i in range(5)) for j in range(10)]
将尝试1中的第一个函数(fun
)保存在py文件中,然后导入它
import multiprocessing
pool = multiprocessing.Pool(8)
import fun
if__name__ == '__main__':
score_mlt_pr = pool.map(fun.fun, products ) #products is the cartesian product same as attempt 1
scores_mlt = list(score_mlt_pr)
多处理尝试2:
import random , string , itertools , difflib
from functools import partial
N = 10
random.seed(123)
words = [''.join(random.choice(string.ascii_lowercase) for i in range(5)) for j in range(10)]
使用与前面尝试2相同的f
,但使用池:
close_matches = list(pool.map(f,words))
通过多处理,所花费的时间会减少,但对于1000*48000个字的组合,所花费的时间仍约为1小时
我希望我能为我的问题提供一个明确的例子。请告知我如何加速我的代码 这种方法会有更好的性能
words = <wordlist>
res = []
while len(words) > 4:
# get a word from list
word=words.pop()
# Find three closest to it
closest = difflib.get_close_matches(word, possibilities=words, n=3, cutoff=0.4)
#remove found words from list
for w in closest:
words.remove(w)
#add fourth word to list
closest.append(word)
res.append(closest)
现在,res在字典中的元素和列表中唯一的单词一样多。唯一的问题是“数据质量”。随着迭代过程中列表的缩小,get_Nestest_match方法查找匹配单词的选项越来越少。所以最后几轮没有找到最适合这个词的匹配词。另一方面,这种方法和以前的方法一样快
结果是否可接受取决于您在何处使用此数据 您好,谢谢您的回答,但是我希望尽可能多的列表作为输入。不是N/4,所以我第二次尝试的输出是我想要的,但是使用了一种更快的方法。然后,我将创建一个字典,单词作为键,匹配项作为值。一个非常简单的优化就是利用对称性,将
itertools.product(单词,单词)
替换为itertools.compositions(单词)
。这将使计算数量减少一点,超过2倍。但是,只要将每个单词与每个单词进行比较,您的算法将按O(n^2)进行缩放。如果有关于单词的其他已知事实(例如,固定长度、仅ascii码,如您的示例中所示),那么您可以进一步优化