比较多个Python列表并在Levenshtein相似性上合并

比较多个Python列表并在Levenshtein相似性上合并,python,list,function,compare,levenshtein-distance,Python,List,Function,Compare,Levenshtein Distance,我已经编写了一个Python函数,它获取两个列表,使用Levenshtein对它们进行比较,并将足够相似的单词合并到一个名为“merged”的列表中 如何为6+个列表执行此操作?确保将每个列表与其他5个列表进行比较,依此类推 first_list=[“鼠标”、“猫”、“狗”、“小精灵”、“马”] 第二个列表=[“鼠标”、“猫”、“Hors”、“狗”、“小鬼”] 第三个列表=[“鼠标”、“猫”、“熊”、“狗”、“贪婪”] 第四个列表=[“鼠标”、“美食”、“狗”、“小精灵”、“马”] 第五个列表=

我已经编写了一个Python函数,它获取两个列表,使用Levenshtein对它们进行比较,并将足够相似的单词合并到一个名为“merged”的列表中

如何为6+个列表执行此操作?确保将每个列表与其他5个列表进行比较,依此类推

first_list=[“鼠标”、“猫”、“狗”、“小精灵”、“马”]
第二个列表=[“鼠标”、“猫”、“Hors”、“狗”、“小鬼”]
第三个列表=[“鼠标”、“猫”、“熊”、“狗”、“贪婪”]
第四个列表=[“鼠标”、“美食”、“狗”、“小精灵”、“马”]
第五个列表=[“莫斯”、“猫”、“霍斯”、“狗”、“小鬼”]
第六个列表=[“鼠标”、“猫”、“骑士”、“多格”、“小鬼”]
def lev_合并(a,b):#用于比较两个列表的函数
merged=[]#空列表以添加匹配的单词
对于a中的第一个:
对于b中的第二个:
如果levenshtein(第一,第二)<2:
merged.append(set([first,second]))
返回合并
打印(级别合并(第一个列表,第二个列表))

我们将有一个字符串列表

list_of_lists = [["Mouse", "Cat", "Dog", "Gremlinge", "Horse"],
                  ["Mouse", "Cat", "Hors", "Dog", "Gremling"],
                  ["Mouse", "Cat", "Horrs", "Dog", "Greemling"],
                  ["Mouse", "Cate", "Dog", "Gremlinge", "Horse"],
                  ["Mose", "Cat", "Hors", "Dog", "Gremling"],
                  ["Mouse", "Cat", "Horser", "Doeg", "Gremling"]]
然后,我们将遍历这个列表,跟踪我们“所在”列表的索引,并将这个列表与它后面的所有列表进行比较

def merging(list_of_lists):
    merged = []
    for i, a in enumerate(list_of_lists):
        for b in list_of_lists[i+1:]:
            for first in a:
                for second in b:
                    if lev(first, second) < 2:
                        merged.append((first, second))
    return merged

numberofmatches
基本上是您的Levenshtein代码,只是它只返回两个列表之间匹配的单词数。即使这不是你想要的,这也会让你知道如何到达那里。

这个答案有两个解决方案。对于这两种情况,您都需要创建一个包含所有要比较的列表的列表

例如,使用上述案例,您可以执行以下操作:

lists = [first_list, second_list]
ITERTOOLS解决方案

在这个解决方案中,您使用了
itertools.combines
方法,该方法遍历每个可能的组合,这意味着它将每个列表与其他列表进行比较。您可以这样实现它:

import itertools
for a, b in itertools.combinations(lists, 2):
    for first in a:
        for second in b:
            if levenshtein(first, second) < 2:
                merged.append(first)
返回:

('A', 'B')
('A', 'C')
('A', 'D')
('B', 'C')
('B', 'D')
('C', 'D')
('A', 'B', 'C')
('A', 'B', 'D')
('A', 'C', 'D')
('B', 'C', 'D')
以及:

返回:

('A', 'B')
('A', 'C')
('A', 'D')
('B', 'C')
('B', 'D')
('C', 'D')
('A', 'B', 'C')
('A', 'B', 'D')
('A', 'C', 'D')
('B', 'C', 'D')
用于循环解决方案

如果你不想导入一些奇怪的模块,别担心。您始终可以使用此解决方案,它只需要2个
循环

for i in range(len(lists)):
    for j in range(i + 1, len(lists)):
        for first in lists[i]:
            for second in lists[j]:
                if levenshtein(first, second) < 2:
                    merged.append(set([first,second]))
范围内的i(len(列表)):
对于范围内的j(i+1,len(列表)):
对于列表中的第一位[i]:
对于列表中的第二个[j]:
如果levenshtein(第一,第二)<2:
merged.append(set([first,second]))

通过这样做,您可以成功地将每个列表中的每个项目与其他列表中的每个项目进行比较,而无需将两个列表进行两次比较。

因此,您希望将
第一个列表中的每个单词与
第二个列表中的每个单词进行比较。
?感谢您的评论。不,这是我的函数目前所做的。我已经更新了帖子以显示其他4个列表,我希望我的函数也能通过这些列表,并根据相似性进行合并。你能给出一个你想要的示例输出吗?您是否希望结果是一个列表,其中列表中的每个元素都是所有列表中所有“关闭”单词的集合。所以,
[{“鼠标”,“莫斯”},{“猫”,“美食”},…]
是的,谢谢,这正是我要找的。最好我也只想合并“关闭”的话,并进入他们自己的名单,如果他们来自3个或更多的名单,这将需要某种计数器,我想?这真是太棒了,正是我所寻找的!然而,是否有可能以某种方式将相似的单词分组并排除/删除重复的单词?如果合并了3个以上的列表,是否可以只返回合并列表?您将如何对它们进行分组?如果
A
B
足够相似,
B
C
足够相似,
A
B
C
在同一组中,即使
A
C
不相似,这是一个很好的问题。我实际上在寻找一种解决方案,根据匹配或“关闭”单词的数量以及这些单词来自的列表的数量,将列表合并到单独的列表中。假设有3个列表,其中有6个匹配的动物词:
列表A
列表B
列表C
,我希望它们合并在
列表1
中,没有重复项。但是
列表D
列表E
,以及6个关于其他事物的匹配词,不会被匹配,因为它们仅来自2个列表。如果
列表A
列表B
列表C
的匹配单词少于6个,它们也不会被合并。您的编辑看起来超级棒,就像我正在寻找的一样。尽管我恐怕不明白if
匹配的数量(a,b)>=target\u num\u单词:
行?我怎样才能调用这样的变量?还是我完全误解了什么?这就是你建议我添加并重写Levenshtein脚本的地方吗?
number of_matches
将是一个函数(我没有编写它,因为它不是真正相关的),它包含两个列表,并返回这两个列表之间的匹配数。这也正是我想要的,谢谢。使用itertools在速度方面有什么优势吗?此外,是否可以根据词组对结果列表进行分组并消除重复项?因此,Horse、Horser和Hors将被分组并只显示一次?
Itertools
是用C编写的,因此我认为,由于C的速度是Python的400倍,因此该模块应该要快一点。然而,我不能完全肯定。
for i in range(len(lists)):
    for j in range(i + 1, len(lists)):
        for first in lists[i]:
            for second in lists[j]:
                if levenshtein(first, second) < 2:
                    merged.append(set([first,second]))