10

difflib python パッケージを使用しています。引数を設定isjunkしても、計算された比率は同じです。isjunkの場合、スペースの違いは無視されませんlambda 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
4

3 に答える 3

5

isjunkあなたが思っているよりも少し違った働きをします。一般にisjunk、一致の長さには影響しないが、合計文字数には含まれている 1 つまたは複数の文字を識別するだけです。たとえば、次のことを考慮してください。

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

2 番目の文字列 ( ) の最初の 4 文字"abcd"はすべて無視できるため、2 番目の文字列はスペースで始まる最初の文字列と比較できます。最初の文字列と 2 番目の文字列の両方のスペースから開始すると、上記SequenceMatcherは 10 個の一致する文字 (各文字列に 5 個) と 4 個の一致しない文字 (2 番目の文字列の無視できる最初の 4 文字) を見つけます。これにより、10/14 (0.7142857142857143) の比率が得られます。

あなたの場合、最初の文字"a b c"列は、インデックス 0、1、および 2 で 2 番目の文字列と一致します (values を使用"a b")。最初の文字列 ( " ") のインデックス 3 には一致がありませんが、一致の長さに関しては無視されます。スペースが無視されるため、インデックス 4 ( "c") は 2 番目の文字列のインデックス 3 と一致します。したがって、9 文字のうち 8 文字が一致し、比率は になり0.88888888888888ます。

代わりにこれを試してみてください:

>>> c = a.replace(' ', '')
>>> d = b.replace(' ', '')
>>> difflib.SequenceMatcher(a=c, b=d).ratio()
1.0
于 2013-05-08T12:11:41.973 に答える
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)]

最初の 2 つは、"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」を一致させてから、これら2つのブロックを「a b」にマージし、スペース文字がジャンクであるにもかかわらず、それを一致と呼びます。

于 2013-05-08T03:30:22.787 に答える
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()

(アルゴリズムが隣接する一致を「調整」する方法のため、実際には同じです)。

比率は、これらの一致の長さとオリジナル (ジャンクを含む) の長さにのみ依存するため、同じ比率が得られます。

于 2013-05-08T03:55:36.940 に答える