difflib.SequenceMatcher的isjunk参数未被考虑?

7
在Python difflib库中,SequenceMatcher类的行为是否出乎意料,还是我误解了所谓的行为?
为什么在这种情况下isjunk参数似乎没有任何影响?
difflib.SequenceMatcher(None, "AA", "A A").ratio() return 0.8

difflib.SequenceMatcher(lambda x: x in ' ', "AA", "A A").ratio() returns 0.8

我的理解是,如果省略了空格,则比率应为1。
2个回答

2
这是因为ratio函数在计算比率时使用了总序列长度,但它没有使用isjunk过滤元素。因此,只要匹配块中的匹配数结果相同(有或没有使用isjunk),比率度量值就会相同。
我认为没有使用isjunk来过滤序列是出于性能方面的考虑。
def ratio(self):   
    """Return a measure of the sequences' similarity (float in [0,1]).

    Where T is the total number of elements in both sequences, and
    M is the number of matches, this is 2.0*M / T.
    """

    matches = sum(triple[-1] for triple in self.get_matching_blocks())
    return _calculate_ratio(matches, len(self.a) + len(self.b))

self.aself.b是传递给SequenceMatcher对象的字符串(序列)(例如您示例中的“AA”和“A A”)。isjunk函数lambda x:x in' '仅用于确定匹配块。您的示例非常简单,因此两次调用的结果比率和匹配块都相同。

difflib.SequenceMatcher(None, "AA", "A A").get_matching_blocks()
[Match(a=0, b=0, size=1), Match(a=1, b=2, size=1), Match(a=2, b=3, size=0)]

difflib.SequenceMatcher(lambda x: x == ' ', "AA", "A A").get_matching_blocks()
[Match(a=0, b=0, size=1), Match(a=1, b=2, size=1), Match(a=2, b=3, size=0)]

相同的匹配块,比率为: M = 2,T = 6 => 比率 = 2.0 * 2 / 6

现在考虑以下示例:

difflib.SequenceMatcher(None, "AA ", "A A").get_matching_blocks()
[Match(a=1, b=0, size=2), Match(a=3, b=3, size=0)]

difflib.SequenceMatcher(lambda x: x == ' ', "AA ", "A A").get_matching_blocks()
[Match(a=0, b=0, size=1), Match(a=1, b=2, size=1), Match(a=3, b=3, size=0)]

现在匹配的块是不同的,但比例仍然相同,因为匹配数量仍相等:

isjunk为 None 时M = 2, T = 6 => ratio = 2.0 * 2 / 6

isjunklambda x: x == ' '时:M = 1 + 1, T = 6 => ratio = 2.0 * 2 / 6

最后,匹配数量不同:

difflib.SequenceMatcher(None, "AA ", "A A ").get_matching_blocks()
[Match(a=1, b=0, size=2), Match(a=3, b=4, size=0)]

difflib.SequenceMatcher(lambda x: x == ' ', "AA ", "A A ").get_matching_blocks()
[Match(a=0, b=0, size=1), Match(a=1, b=2, size=2), Match(a=3, b=4, size=0)]

The number of matches is different.
isjunk 为 None 时: M = 2, T = 7 => ratio = 2.0 * 2 / 7isjunklambda x: x == ' ' 时: M = 1 + 2, T = 6 => ratio = 2.0 * 3 / 7

5
如果isjunk无法起到这种作用,那么如何匹配和忽略像问题示例中的一些简单字符行?更具体地说,是否有内置的函数/方法可以在计算相似度比率时简单地忽略某些字符? - appwizcpl
同意,当它本身并没有“做任何事情”时使用这个属性确实有些奇怪。 - CutePoison

0

在对字符串进行排序之前,您可以从中删除字符。

def withoutJunk(input, chars):
    return input.translate(str.maketrans('', '', chars))

a = withoutJunk('AA', ' ')
b = withoutJunk('A A', ' ')
difflib.SequenceMatcher(None, a, b).ratio()
# -> 1.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接