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

时间:2013-05-08 02:59:01

标签: 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

3 个答案:

答案 0 :(得分:4)

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

>>> SequenceMatcher(lambda x: x in "abcd", " abcd", "abcd abcd").ratio()
0.7142857142857143

第二个字符串("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

答案 1 :(得分: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)]

前两个告诉你它将“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.

这意味着首先它认为“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.

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

答案 2 :(得分:0)

两个调用的匹配数相同(3)。您可以使用以下方法检查:

print difflib.SequenceMatcher(isjunk=lambda x: x == " ", a="a b c", b="a bc").get_matching_blocks()
print difflib.SequenceMatcher(a="a b c", b="a bc").get_matching_blocks()

(它们实际上是相同的,因为算法“调整”相邻匹配的方式。)

由于比率仅取决于这些比赛的长度和原件的长度(包括垃圾),因此您可获得相同的口粮。