Można zobaczyć to, co uważa za dopasowane bloki:
>>> 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)]
Pierwsze dwa powiedzieć, że mecze "a b" do "b" i "c" na "c". (Ostatni jest banalny)
Pytanie brzmi, dlaczego można dopasować "a b". Odpowiedź znalazłem w kodzie. Najpierw algorytm znajduje grupę dopasowanych bloków, wielokrotnie wywołując find_longest_match. Co godne uwagi o find_longest_match jest to, że pozwala postać śmieci istnieć na końcach łańcucha:
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.
oznacza to, że pierwszy uzna „a” i „b” do bycia mecze (pozwalające na charakter miejsca na koniec "a" i na początku "b").
Następnie interesująca część: kod wykonuje jedną ostatnią kontrolę, aby zobaczyć, czy któryś z bloków sąsiaduje z nim i scala je, jeśli są. Zobacz ten komentarz w kodzie:
# 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.
więc w zasadzie to dopasowanie „a” i „b”, a następnie łącząc te dwa bloki na „a b” i nazywając że mecz pomimo znak spacji jest śmieci.
może być źle, ale 'A' i' B' zarówno zasadniczo stać ' "abc"' jeżeli ich przestrzenie są ignorowane przez 'difflib'? – mdscruggs
yes i to zwróci '1.0' –
2.7 docstring dla SequenceMatcher:" .ratio() zwraca wartość zmiennoprzecinkową w [0, 1], mierząc "podobieństwo" sekwencji . Zgodnie z regułą, .ratio () wartość powyżej 0,6 oznacza, że sekwencje są bliskimi odpowiednikami " – mdscruggs