【问题标题】:Replace strings based on similarity根据相似性替换字符串
【发布时间】:2019-07-31 17:23:22
【问题描述】:

我正在尝试用另一个列表中的字符串替换一个列表中的字符串。

strlist = ['D-astroid 3-cyclone', 'DL-astroid 3-cyclone', 'DL-astroid', 'D-comment', 'satellite']
to_match = ['astroid 3-cyclone', 'D-comment', 'D-astroid']

预期输出:

str_list = ['astroid 3-cyclone', 'astroid 3-cyclone', 'D-astroid', 'D-comment', 'satellite']

并输出包含映射的字典

dict = 
{'astroid 3-cyclone':['astroid 3-cyclone', 'astroid 3-cyclone'],
'D-comment':'D-comment',
'D-astroid':'DL-astroid',
}

我正在尝试通过以下方式使用difflib 为测试用例实现它,

from difflib import SequenceMatcher
from pprint import pprint


def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()


strlist = ['D-astroid 3-cyclone', 'DL-astroid 3-cyclone', 'DL-astroid', 'D-comment']
to_match = ['astroid 3-cyclone', 'D-comment', 'D-astroid']
similarity = similar('DL-astroid', 'astroid 3-cyclone')
pprint(similarity)

基本上,如果相似度匹配在 0.9 或 0.85 以上,strlist 中的字符串必须替换为to_match 列表中的字符串。可以使用两个for 循环来检查strlist 中的项目是否与to_match 中的项目具有高相似率(>0.9)。我不确定这是否是一种有效的实施方式。

有什么建议吗?

编辑:我的尝试,但我不确定如何创建字典。

from difflib import SequenceMatcher
from pprint import pprint
def similar(a, to_match):
    percent_similarity = [SequenceMatcher(None, a, b).ratio() for b in to_match]
    max_value_index = [i for i, j in enumerate(percent_similarity) if j == max(percent_similarity)][0]
    map = [to_match[max_value_index] if max(percent_similarity) > 0.9 else a][0]
    return map


strlist = ['D-saturn 6-pluto', 'D-astroid 3-cyclone', 'DL-astroid 3-cyclone', 'DL-astroid', 'D-comment', 'literal']
to_match = ['saturn 6-pluto', 'pluto', 'astroid 3-cyclone', 'D-comment', 'D-astroid']

map = [similar(item, to_match) for item in strlist]
pprint(map)

【问题讨论】:

  • 你试过了吗?结果如何?
  • @glibdud 是的,我已将代码添加到我的原始帖子中。有兴趣的可以看看

标签: python string str-replace string-comparison


【解决方案1】:

您可以从第二个列表制作字典并将其应用于第一个:

strlist = ['D-astroid 3-cyclone', 'DL-astroid 3-cyclone', 'DL-astroid', 'D-comment', 'satellite']
to_match = ['astroid 3-cyclone', 'D-comment', 'D-astroid']
d1 = {i.split('-')[-1]:i for i in to_match}
result1 = [d1.get(i.split('-')[-1], i) for i in strlist]
result2 = {b:[i for i in strlist if i.endswith(a)] for a, b in d1.items()}
result2 = {a:b if len(b) != 1 else b[0] for a, b in result2.items()}

输出:

['astroid 3-cyclone', 'astroid 3-cyclone', 'D-astroid', 'D-comment', 'satellite']
{'astroid 3-cyclone': ['D-astroid 3-cyclone', 'DL-astroid 3-cyclone'], 'D-comment': 'D-comment', 'D-astroid': 'DL-astroid'}

【讨论】:

  • @Akaisteph7 当然可以,但我认为,考虑到输入字符串结构,使用简单的分组算法创建这样的相似性是可能的。
  • 啊,是的。我误解了。然而,这依赖于所有字符串将始终具有这种一般结构的假设。
  • 是的,所有字符串都具有相同的一般结构
  • @Ajax1234 我还是更喜欢使用来自difflibSequenceMatcher。有如下测试用例strlist = ['D-saturn 6-pluto']to_match = ['saturn 6-pluto','pluto']。得到的输出:['pluto']。预期输出:['saturn-6-pluto']
猜你喜欢
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多