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码,如您的示例中所示),那么您可以进一步优化