get_opcodes()
返回描述如何将 a 变为 b 的 5 元组列表,每个元组的形式为 (tag, i1, i2, j1, j2)。 在第一个元组中 i1 == j1 == 0,而在其余的元组中 i1 等于前一个元组的 i2,并且 j1 也等于前一个元组的 j2。
tag 值为字符串,其含义如下:
值 | 含义 |
---|---|
'replace' | a[i1:i2] 应由 b[j1:j2] 替换。 |
'delete' | a[i1:i2] 应被删除。 请注意在此情况下 j1 == j2。 |
'insert' | b[j1:j2] 应插入到 a[i1:i1]。 请注意在此情况下 i1 == i2。 |
'equal' | a[i1:i2] == b[j1:j2] (两个子序列相同)。 |
>>> a = "qabxcd"
>>> b = "abycdf"
>>> s = SequenceMatcher(None, a, b)
>>> for tag, i1, i2, j1, j2 in s.get_opcodes():
... print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(
... tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))
delete a[0:1] --> b[0:0] 'q' --> ''
equal a[1:3] --> b[0:2] 'ab' --> 'ab'
replace a[3:4] --> b[2:3] 'x' --> 'y'
equal a[4:6] --> b[3:5] 'cd' --> 'cd'
insert a[6:6] --> b[5:6] '' --> 'f'
def compared_str(a, b):
assert isinstance(a, str)
assert isinstance(b, str)
result_a = ''
result_b = ''
s = difflib.SequenceMatcher(None, a, b, autojunk=False)
for tag, i1, i2, j1, j2 in s.get_opcodes():
# print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))
if tag == "equal":
if a[i1:i2]:
result_a += a[i1:i2]
if b[j1:j2]:
result_b += b[j1:j2]
else:
if a[i1:i2]:
result_a += f'<em>{a[i1:i2]}</em>'
if b[j1:j2]:
result_b += f'<em>{b[j1:j2]}</em>'
return result_a, result_b