我正在尝试创建一个名称匹配器,以比较说'JOHN LEWIS''JOHN SMITH LEWIS'。他们显然是同一个人,我想创建一个函数,当您输入这些名称时,它将变成一个列表,然后为您提供匹配的名称。

问题是我的循环返回'LEWIS''LEWIS'匹配,而'SMITH''LEWIS'匹配,这是因为它的顺序。

from pyjarowinkler import distance

entered_name = 'JOHN LEWIS'.split(' ')  # equals ['JOHN','LEWIS']
system_name = 'JOHN SMITH LEWIS'.split(' ')  # equals ['JOHN','SMITH','LEWIS']

ratio = []

for i in entered_name:
    maximum = 0
    for j in system_name:
        score = distance.get_jaro_distance(i, j, winkler=True,
                                           scaling=0.1)
        while score > maximum:
            maximum = score
            new = (i, j, maximum)
            system_name.remove(i)
            #removes that name from the original list
    ratio.append(new)


会返回如下内容:[('JOHN', 'JOHN', 1.0), ('LEWIS', 'SMITH', 0.47)]

而不是:[('JOHN', 'JOHN', 1.0), ('LEWIS', 'LEWIS', 1.0)]
另外,如果您尝试使用'ALLY A ARM'之类的'ALLY ARIANA ARMANI',如果您不执行'ALLY'行,它会与remove(i)匹配两次。这就是为什么我只想要独特的比赛!

我只是不断收到错误或找不到的答案。

最佳答案

问题出在您的system_name.remove(i)行上。首先,在遍历列表时修改列表通常是个坏主意。这可能导致意外行为。就您而言,这是您的代码正在执行的操作:


第一次通过,匹配'JOHN''JOHN'。没问题。
'JOHN'中删除​​system_name。现在system_name = ['SMITH', 'LEWIS']
第二次通过i = 'LEWIS'j = 'SMITH'score = .47大于0,因此您的支票score > maximum通过
我们设置maximum = score
我们设置new = ('LEWIS', 'SMITH', 0.47)
我们从'LEWIS'中删除​​system_name。现在system_name = ['SMITH']。呃哦


下面使用if而不是while循环进行简单重写,因为完全不需要while循环:

for i in entered_name:
    maximum = 0
    for j in system_name:
        score = distance.get_jaro_distance(i, j, winkler=True,
                                           scaling=0.1)
        if score > maximum:
            maximum = score
            new = (i, j, maximum)
    system_name.remove(new[1])  # want to remove 'SMITH' in the example, not 'LEWIS'
    ratio.append(new)


我所做的只是将system_name.remove()调用移到system_name循环之外,并用i替换j(使用new[1],因为我不在j循环之外)。

10-04 13:49