给定两个长度相同的python列表。如何返回相似值的最佳匹配?

给定两个长度相同的python列表。如何返回相似值的最佳匹配?,python,string,list,mapping,Python,String,List,Mapping,给出了两个包含字符串的python列表(人名): 我想要最相似的名字的映射 'J. Payne' -> 'John Payne' 'George Bush' -> 'George W. Bush' 'Billy Idol' -> 'Billy Idol' 'M Stuart' -> 'M. Stuart' 'Luc van den Bergen' -> 'Luc Bergen' 在python中

给出了两个包含字符串的python列表(人名):

我想要最相似的名字的映射

'J. Payne'           -> 'John Payne'
'George Bush'        -> 'George W. Bush'
'Billy Idol'         -> 'Billy Idol'
'M Stuart'           -> 'M. Stuart'
'Luc van den Bergen' -> 'Luc Bergen'

在python中有没有一种简洁的方法可以做到这一点?这些列表平均包含5到6个名称。有时更多,但这很少。有时每个列表中只有一个名称,拼写可能略有不同。

使用此处定义的函数:

J.佩恩==>约翰·佩恩 乔治·布什==>乔治·W·布什 比利偶像==>比利偶像 M斯图尔特==>M斯图尔特 吕克·范登伯根==>吕克·伯根
您可以尝试
difflib

import difflib

list_1 = ['J. Payne', 'George Bush', 'Billy Idol', 'M Stuart', 'Luc van den Bergen']
list_2 = ['John Payne', 'George W. Bush', 'Billy Idol', 'M. Stuart', 'Luc Bergen']

mymap = {}
for elem in list_1:
    closest = difflib.get_close_matches(elem, list_2)
    if closest:
        mymap[elem] = closest[0]

print mymap
输出:

{'George Bush': 'George W. Bush', 
 'Luc van den Bergen': 'Luc Bergen', 
 'Billy Idol': 'Billy Idol', 
 'J. Payne': 'John Payne', 
 'M Stuart': 'M. Stuart'}

下面是给定解决方案的一个变体,它还优化了 全局最小距离。它使用 以确保字符串对是最佳的

from munkres import Munkres
def match_lists(l1, l2):
    # Compute a matrix of string distances for all combinations of
    # items in l1 and l2.
    matrix = [[levenshtein(i1, i2) for i2 in l2] for i1 in l1]

    # Now figure out what the global minimum distance between the
    # pairs is.
    indexes = Munkres().compute(matrix)
    for row, col in indexes:
        yield l1[row], l2[col]

l1 = [
    'bolton',
    'manchester city',
    'manchester united',
    'wolves',
    'liverpool',
    'sunderland',
    'wigan',
    'norwich',
    'arsenal',
    'aston villa',
    'chelsea',
    'fulham',
    'newcastle utd',
    'stoke city',
    'everton',
    'tottenham',
    'blackburn',
    'west brom',
    'qpr',
    'swansea'
    ]
l2 = [
    'bolton wanderers',
    'manchester city',
    'manchester united',
    'wolverhampton',
    'liverpool',
    'norwich city',
    'sunderland',
    'wigan athletic',
    'arsenal',
    'aston villa',
    'chelsea',
    'fulham',
    'newcastle united',
    'stoke city',
    'everton',
    'tottenham hotspur',
    'blackburn rovers',
    'west bromwich',
    'queens park rangers',
    'swansea city'
    ]
for i1, i2 in match_lists(l1, l2):
    print i1, '=>', i2
对于给定的列表,其中差异更多来自于备选方案 拼写和昵称,而不是拼写错误,这种方法提供了更好的结果,而不仅仅是拼写错误 使用levenshtein或difflib。munkres模块可在此处找到:

您对“最相似”的算法定义是什么?@cdhowie:名称的不同拼写、名称的缩写、诸如比利时“van”等中间词的可选可用性、可选中间名。我不知道如何用算法来定义它。我想映射那些拼写最接近的名字。为了做到这一点,你需要将你关于名字“接近度”的想法转化为一个可以应用于两个字符串的函数。计算机不会处理模糊的规格;他们处理数学问题@谢谢你的建议。我希望有一个python模块能够做到这一点,因为我不想重新发明轮子。例如,下面提到的
difflib
模块。但是你在数学和计算机方面提出了一个观点。:-)列表的大小是否始终相同,列表_2中的每个项目是否始终只有一个匹配项?如果是这样,距离匹配可以大大改进。levenstein函数与@jellybean?@Aufwind的
difflib.get_Nestest_matches()
方法之间的主要区别是什么?我认为difflib使用了完全不同的算法。帮助说它使用SequenceMatcher。如果不知道它将用于哪些数据,很难确定哪种算法会更好。
>>> from functools import partial
>>> for i in list_1:
...     print i, '==>', min(list_2, key=partial(levenshtein,i))
...
J. Payne ==> John Payne George Bush ==> George W. Bush Billy Idol ==> Billy Idol M Stuart ==> M. Stuart Luc van den Bergen ==> Luc Bergen
import difflib

list_1 = ['J. Payne', 'George Bush', 'Billy Idol', 'M Stuart', 'Luc van den Bergen']
list_2 = ['John Payne', 'George W. Bush', 'Billy Idol', 'M. Stuart', 'Luc Bergen']

mymap = {}
for elem in list_1:
    closest = difflib.get_close_matches(elem, list_2)
    if closest:
        mymap[elem] = closest[0]

print mymap
{'George Bush': 'George W. Bush', 
 'Luc van den Bergen': 'Luc Bergen', 
 'Billy Idol': 'Billy Idol', 
 'J. Payne': 'John Payne', 
 'M Stuart': 'M. Stuart'}
from munkres import Munkres
def match_lists(l1, l2):
    # Compute a matrix of string distances for all combinations of
    # items in l1 and l2.
    matrix = [[levenshtein(i1, i2) for i2 in l2] for i1 in l1]

    # Now figure out what the global minimum distance between the
    # pairs is.
    indexes = Munkres().compute(matrix)
    for row, col in indexes:
        yield l1[row], l2[col]

l1 = [
    'bolton',
    'manchester city',
    'manchester united',
    'wolves',
    'liverpool',
    'sunderland',
    'wigan',
    'norwich',
    'arsenal',
    'aston villa',
    'chelsea',
    'fulham',
    'newcastle utd',
    'stoke city',
    'everton',
    'tottenham',
    'blackburn',
    'west brom',
    'qpr',
    'swansea'
    ]
l2 = [
    'bolton wanderers',
    'manchester city',
    'manchester united',
    'wolverhampton',
    'liverpool',
    'norwich city',
    'sunderland',
    'wigan athletic',
    'arsenal',
    'aston villa',
    'chelsea',
    'fulham',
    'newcastle united',
    'stoke city',
    'everton',
    'tottenham hotspur',
    'blackburn rovers',
    'west bromwich',
    'queens park rangers',
    'swansea city'
    ]
for i1, i2 in match_lists(l1, l2):
    print i1, '=>', i2