1.4.3 比较任意类型
SequenceMatcher类可以比较任意类型的两个序列,只要它们的值是可散列的。这个类使用一个算法来标识序列中最长的连续匹配块,并删除对实际数据没有贡献的无用值。函数get_opcodes()返回一个指令列表来修改第一个序列,使它与第二个序列匹配。这些指令被编码为5元素元组,包括一个字符串指令(“操作码”)和序列的两对开始及结束索引(表示为i1、i2、j1、j2)。如图1-4所示。
表1-4 difflib.get_opcodes()指令
操作码 | 定义 |
---|---|
‘replace’ | 将a[i1:i2]替换为b[j1:j2] |
‘delete’ | 完全删除a[i1:i2] |
‘insert’ | 将b[j1:j2]插入a[i1:i2] |
‘equal’ | 两个序列已经相等 |
import difflib
s1 = [1,2,3,5,6,4]
s2 = [2,3,5,4,6,1]
print('Initial data:')
print('s1 =',s1)
print('s2 =',s2)
print('s1 == s2:',s1 == s2)
print()
matcher = difflib.SequenceMatcher(None,s1,s2)
for tag,i1,i2,j1,j2 in reversed(matcher.get_opcodes()):
if tag == 'delete':
print('Remove {} from positions [{}:{}]'.format(
s1[i1:i2],i1,i2))
print(' before =',s1)
del s1[i1:i2]
elif tag == 'equal':
print('s1[{}:{}] and s2[{}:{}] are the same'.format(
i1,i2,j1,j2))
elif tag == 'insert':
print('Insert {} from s2[{}:{}] into s1 at {}'.format(
s2[j1:j2],j1,j2,i1))
print(' before=',s1)
s1[i1:i2] = s2[j1:j2]
elif tag == 'replace':
print(('Replace {} from s1[{}:{}] '
'with {} from s2[{}:{}]').format(
s1[i1:i2],i1,i2,s2[j1:j2],j1,j2))
print(' before=',s1)
s1[i1:i2] = s2[j1:j2]
print(' after =',s1, '\n')
print('s1 == s2:',s1 == s2)
这个例子比较了两个整数列表,并使用get_opcodes()得出将原列表转换为新列表的指令。这里以逆序应用所做的修改,以便增加和删除元素之后的列表所有仍是正确的。
SequenceMatcher用于处理定制类以及内置类型,前提是它们必须是可散列的。
运行结果: