【问题标题】:Python code to extract similar strings from 2 lists从 2 个列表中提取相似字符串的 Python 代码
【发布时间】:2020-02-09 14:09:55
【问题描述】:

我有 2 个来自 2 个不同来源的玩家姓名列表。

names1 = ['C.J. McCollum', 'Metta World', 'LeBron James', 'Stephen Curry']

names2 = ['Metta World Peace', 'Steph Curry', 'Kevin Durant', 'CJ McCollum']

这里的问题是,尽管他们是同一个球员,但在 2 个来源中提到他们名字的方式存在一些差异。我使用以下代码查找相似的名称(names1 中的所有字符都应存在于names2 中):

idx = np.zeros(3)
i = 0
for x, y in enumerate(names1):
    for z, w in enumerate(names2):
        if y in w:
            idx[i] = x
            i = i+1

对于names1的每次迭代,names2的所有迭代中的代码,并输出与names2中的条目相似的条目的索引。 idx 是一个列表,应该包含相似字符串的索引。 iidx 的索引。每次找到类似的字符串时,将其存储在idx 中,i 增加 1,以便将找到的下一个条目记录在索引 i+1idx 中。

预期答案: idx = [0, 1, 3]

但是我收到以下错误: list assignment index out of range

我该如何修复代码,有没有更好的方法来解决这个问题?

【问题讨论】:

  • 即使你没有错误,你的结果将是一个空数组或全为零,我认为你正在寻找y in w,关于你的问题我不认为有一个通用的解决方案可以在没有一些基本规则的情况下找到相似的字符串
  • 感谢您指出我的错误。我已经更新了我的问题。 (对于给您带来的不便,我深表歉意,我还是 Stack Overflow 的新手)

标签: python string for-loop if-statement


【解决方案1】:

由于 y in z: 出现错误,您可以在 w: 中使用 y 你也可以做一些格式化,比如删除“。”在比较之前,然后您可以使用任何字符串相似性算法(例如 Levenshtein 距离)来查找相似的字符串, "pip install python-Levenshtein"

import numpy as np
import Levenshtein as ld

names1 = ['C.J. McCOllum', 'Metta World Peace', 'LeBron James', 'Stephen 
Curry']

names2 = ['Metta World Peace', 'Steph Curry', 'Kevin Durant', 'CJ McCollum']
idx = np.zeros(3)
i = 0
similarity_index =3
for x, y in enumerate(names1):
y=y.replace('.','')

for z, w in enumerate(names2):
    w= w.replace('.','')
    if ld.distance(y,w) < similarity_index:
        idx[i] = x
        i = i+1


 print(idx)

【讨论】:

  • 对于这些我已经提到了一些算法可以像 Levenshtein distance 来计算字符串之间的相似度,并且可以设置一些阈值距离值来考虑字符串相似度。
  • 最好在答案中发布实现
【解决方案2】:

这是一个尝试(这里我认为只有像 M.C = MC、majuscule 和 minicule 的使用以及小于 2 的 Levenshtein 距离这样的变化才被认为是两个名称相同):

import numpy as np


def levenshtein_distance(v, w):
    n, m = len(v), len(w)
    M = np.zeros((n+1, m+1))
    for i in range(n+1):
        M[i, 0] = i
    for j in range(m+1):
        M[0, j] = j
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if v[i-1] == w[j-1]:
                M[i, j] = min(M[i-1, j] + 1, M[i, j-1] + 1, M[i-1, j-1])
            else:
                M[i, j] = min(M[i-1, j] + 1, M[i, j-1] + 1, M[i-1, j-1] + 1)
    return M[n, m]

def norm_names(x):
    # more names normalization can be added here
    return x.replace(".", "").lower()

names1 = ['C.J. McCollum', 'Metta World Peace', 'LeBron James', 'Stephen Curry']
names2 = ['Metta World Peace', 'Steph Curry', 'Kevin Durant', 'CJ McCollum']

names1 = list(map(norm_names, names1))
names2 = list(map(norm_names, names2))

indices = []
for i, name in enumerate(names1):
    for name2 in names2:
         indices += [i] if levenshtein_distance(name, name2) <= 2 else []

这将返回[0, 1, 3]

【讨论】:

  • 这对斯蒂芬库里和斯蒂芬库里有用吗?
  • 是的,你可以在这个website玩levenshtein距离
猜你喜欢
  • 2015-12-19
  • 1970-01-01
  • 2020-06-23
  • 2018-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多