【问题标题】:What is efficient way to check if current word is close to a word in string?检查当前单词是否接近字符串中的单词的有效方法是什么?
【发布时间】:2020-09-18 05:51:37
【问题描述】:

考虑以下示例:

  1. 示例 1:

    str1 = "wow...it  looks amazing"
    str2 = "looks amazi"
    

    您看到amazi 接近amazingstr2 输入错误,我想编写一个程序告诉我amazi 接近amazing 然后在str2 我将替换amaziamazing

  2. 示例 2:

    str1 = "is looking good"
    str2 = "looks goo"
    

    在这种情况下,更新后的str2 将是"looking good"

  3. 示例 3:

    str1 = "you are really looking good"
    str2 = "lok goo"
    

    在这种情况下,str2 将是"good",因为lok 不接近looking(或者即使程序可以在这种情况下将lok 转换为looking,那么这对于我的问题的解决方案来说很好)

  4. 示例 4:

    str1 = "Stu is actually SEVERLY sunburnt....it hurts!!!"
    str2 = "hurts!!"
    

    更新后的str2 将是"hurts!!!"

  5. 示例 5:

    str1 = "you guys were absolutely amazing tonight, a..."
    str2 = "ly amazin"
    

    更新的str2 将是"amazing""ly" 将被完全删除或替换。

这将是什么算法和代码?

也许我们可以通过按字典顺序查看字符并设置一个 阈值如 0.8 或 80% 所以如果 word2str1 获得 80% 的 word1 连续字符,那么我们将 str2 中的 word2 替换为 str1 的单词? 请问还有其他有效的python代码解决方案吗?

【问题讨论】:

  • python 包pypi.org/project/fuzzywuzzy 可能就是你要找的。​​span>
  • 你应该使用贝叶斯网络来完成这项任务,因为找到正确的世界是一个概率问题
  • 那个包显示比例?我想检查我们在哪里有一个非常接近但不完全相同的单词,此时只需简单地替换为原始单词,您可以发布您的解决方案代码作为答案吗?如果它通过所有测试用例我会接受

标签: python python-3.x string pattern-matching stop-words


【解决方案1】:

在这种情况下,您可以使用 Jacard 系数。首先,您需要按空格分隔第一个和第二个字符串。之后,对于 str2 中的每个字符串,对 str1 中的每个字符串取 Jacard 系数,然后替换为能提供最高 Jacard 系数的字符串。

您可以使用sklearn.metrics.jaccard_score

【讨论】:

  • 您在我投反对票后编辑了您的评论。这就是它被否决的原因。
  • 好的,那你现在对我的回答满意不满意。
【解决方案2】:

像这样:

str1 = "wow...it looks amazing"
str2 =  "looks amazi"
str3 = []

# Checking for similar strings in both strings:
for n in str1.split():
    for m in str2.split():
        if m in n:
            str3.append(n)

# If found 2 similar strings:
if len(str3) == 2:
    # If their indexes align:
    if str1.split().index(str3[1]) - str1.split().index(str3[0]) == 1:
        print(' '.join(str3))

elif len(str3) == 1:
    print(str3[0])

输出:

looks amazing

根据 OP 给出的条件更新:

str1 = "good..."
str2 =  "god.."
str3 = []

# Checking for similar strings in both strings:
for n in str1.split():
    for m in str2.split():

        # Calculating matching character in the 2 words:
        c = ''
        for i in m:
            if i in n:
                c+=i
        # If the amount of matching characters is greater or equal to 50% the length of the larger word
        # or the smaller word is in the larger word:
        if len(list(c)) >= len(n)*0.50 or m in n:
            str3.append(n)


# If found 2 similar strings:
if len(str3) == 2:
    # If their indexes align:
    if str1.split().index(str3[1]) - str1.split().index(str3[0]) == 1:
        print(' '.join(str3))

elif len(str3) == 1:
    print(str3[0])

【讨论】:

  • 我正在用你的代码尝试不同的字符串,但是你的代码很棒,不知道为什么以及谁反对它
  • str1 = "哇...看起来棒极了" str2 = "loks amazi" 这里的 loks 看起来很接近,所以它应该让我看起来很棒,但你的程序给出了“惊人的”
  • 你需要给出一个关于什么是相似的规则。计算机没有感官,所以它们需要规则。例如,如果两个单词有 5 个相同的字母,则告诉计算机两个单词相似的规则。
  • 是否可以通过检查我们有多少个字符匹配来解决某个阈值?
  • @MobassirHossen 是的。能给个吗?
【解决方案3】:

有很多方法可以解决这个问题。这个解决了你所有的例子。我添加了一个最小相似度过滤器来只返回更高质量的匹配。这就是允许在最后一个样本中删除“ly”的原因,因为它并不是所有单词的全部关闭。

Documentation

你可以用pip install python-Levenshtein安装levenshtein

import Levenshtein

def find_match(str1,str2):
    min_similarity = .75
    output = []
    results = [[Levenshtein.jaro_winkler(x,y) for x in str1.split()] for y in str2.split()]
    for x in results:
        if max(x) >= min_similarity:
            output.append(str1.split()[x.index(max(x))])
    return output

您提出的每个样本。

find_match("is looking good", "looks goo")

['looking','good']

find_match("you are really looking good", "lok goo")

['looking','good']

find_match("Stu is actually SEVERLY sunburnt....it hurts!!!", "hurts!!")

['hurts!!!']

find_match("you guys were absolutely amazing tonight, a...", "ly amazin")

['amazing']

【讨论】:

  • 最好的答案,通过每个测试用例,被赞成和接受,没有比这更好的答案了
  • 1 个附加问题:是否可以离线使用您的 python-Levenshtein 代码?此代码在没有互联网的情况下无法使用
  • 此代码不需要互联网连接。如果它失败了,可能是由于其他原因
  • pip install python-Levenshtein 我们不使用互联网进行此安装吗?
  • 哦,是的,但这是一次。您可以将软件包下载到拇指驱动器并在现场从那里安装一次。或者将其安装在一台机器上并将该 python 文件夹复制到拇指驱动器以安装在其他地方。有很多方法可以在没有连接的情况下处理获取 pip 包。
【解决方案4】:

我用正则表达式完成了它

def check_regex(str1,str2):
    #New list to store the updated value
    str_new = []
    for i in str2:
        # regular expression for comparing the strings
        x = ['['+i+']','^'+i,i+'$','('+i+')']
        for k in x:
            h=0
            for j in str1:
                #Conditions to make sure the word is close enough to the particular word
                if "".join(re.findall(k,j)) == i or ("".join(re.findall(k,j)) in i and abs(len("".join(re.findall(k,j)))-len(i)) == 1 and len(i)!=2):
                    str_new.append(j)
                    h=1
                    break
            if h==1:
                break
    return str_new
import re
str1 = input().split()
str2 = input().split()
print(" ".join(check_regex(str1,str2)))

【讨论】:

  • 可能这段代码是错误的,我得到了 g g g g for str1 = "good..." str2 = "goog"
  • 能否请您给出 str1 的完整句子,因为当我运行时它会给我带来好处...
  • 这也是一个例子:str1 = "good..." str2 = "goog" 你的程序失败了
  • 我添加了一张图片,显示它使用我提到的相同代码为我运行
  • 因为 lok 与您在问题中提到的看起来并不接近
猜你喜欢
  • 2013-09-10
  • 2019-07-29
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 2011-07-16
  • 2019-12-29
  • 1970-01-01
相关资源
最近更新 更多