在python中比较字符串时忽略空格

RNA*_*RNA 9 python string difflib

我正在使用difflib python包.无论我是否设置isjunk参数,计算的比率都是相同的.是不是当忽略空间的区别isjunklambda x: x == " "

In [193]: difflib.SequenceMatcher(isjunk=lambda x: x == " ", a="a b c", b="a bc").ratio()
Out[193]: 0.8888888888888888

In [194]: difflib.SequenceMatcher(a="a b c", b="a bc").ratio()
Out[194]: 0.8888888888888888
Run Code Online (Sandbox Code Playgroud)

πόδ*_*κύς 5

isjunk工作方式与您想象的略有不同。通常,isjunk仅标识一个或多个不影响匹配长度但仍包含在总字符数中的字符。例如,请考虑以下情况:

>>> SequenceMatcher(lambda x: x in "abcd", " abcd", "abcd abcd").ratio()
0.7142857142857143
Run Code Online (Sandbox Code Playgroud)

第二个字符串 ( "abcd")的前四个字符都可以忽略,因此可以将第二个字符串与以空格开头的第一个字符串进行比较。从第一个字符串和第二个字符串中的空格开始,然后,上面SequenceMatcher找到十个匹配字符(每个字符串中有五个)和 4 个不匹配字符(第二个字符串中可忽略的前四个字符)。这为您提供了 10/14 (0.7142857142857143) 的比率。

在您的情况下,第一个字符串"a b c"与索引 0、1 和 2 处的第二个字符串相匹配(值为"a b")。第一个字符串 ( " ") 的索引 3没有匹配项,但由于匹配项的长度而被忽略。由于空格被忽略,索引 4 ( "c") 匹配第二个字符串的索引 3。因此,您的 9 个字符中有 8 个匹配,因此您的比率为0.88888888888888.

你可能想试试这个:

>>> c = a.replace(' ', '')
>>> d = b.replace(' ', '')
>>> difflib.SequenceMatcher(a=c, b=d).ratio()
1.0
Run Code Online (Sandbox Code Playgroud)


cha*_*ppy 1

您可以看到它认为什么是匹配块:

>>> difflib.SequenceMatcher(isjunk=lambda x: x == " ", a="a b c", b="a bc").get_matching_blocks()
[Match(a=0, b=0, size=3), Match(a=4, b=3, size=1), Match(a=5, b=4, size=0)]
Run Code Online (Sandbox Code Playgroud)

前两个告诉你它匹配“a b”到“a b”和“c”到“c”。(最后一项是微不足道的)

问题是为什么“a b”可以匹配。我在代码中找到了这个问题的答案。首先,算法通过重复调用find_longest_match来找到一堆匹配块。find_longest_match 值得注意的是它允许垃圾字符存在于字符串的末尾:

If isjunk is defined, first the longest matching block is
determined as above, but with the additional restriction that no
junk element appears in the block.  Then that block is extended as
far as possible by matching (only) junk elements on both sides.  So
the resulting block never matches on junk except as identical junk
happens to be adjacent to an "interesting" match.
Run Code Online (Sandbox Code Playgroud)

这意味着它首先认为“a”和“b”是匹配的(允许“a”末尾和“b”开头有空格字符)。

然后,有趣的部分:代码进行最后一次检查以查看是否有任何块相邻,如果相邻则将它们合并。请看代码中的这条注释:

    # It's possible that we have adjacent equal blocks in the
    # matching_blocks list now.  Starting with 2.5, this code was added
    # to collapse them.
Run Code Online (Sandbox Code Playgroud)

所以基本上它是匹配“a”和“b”,然后将这两个块合并为“a b”并称其为匹配,尽管空格字符是垃圾。