python diff SequenceMatcher-修补列表

python diff SequenceMatcher-修补列表,python,diff,Python,Diff,我将一个列表修补为另一个列表: a = [x for x in "qabxcd"] b = [x for x in "abycdf"] c = a[:] s = SequenceMatcher(None, a, b) for tag, i1, i2, j1, j2 in s.get_opcodes(): print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2]))

我将一个列表修补为另一个列表:

a = [x for x in "qabxcd"]
b = [x for x in "abycdf"]
c = a[:]
s = SequenceMatcher(None, a, b)
for tag, i1, i2, j1, j2 in s.get_opcodes():
    print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % 
    (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2]))
    if tag == "delete":
        del c[i1:i2]
    elif tag == "replace":
        c[i1:i2] = b[j1-1:j2-1]
    elif tag == "insert":
        c[i1:i2] = b[j1:j2]
print c
print b
print c == b
a == b
但名单并不相同:

 delete a[0:1] (['q']) b[0:0] ([])
  equal a[1:3] (['a', 'b']) b[0:2] (['a', 'b'])
replace a[3:4] (['x']) b[2:3] (['y'])
  equal a[4:6] (['c', 'd']) b[3:5] (['c', 'd'])
 insert a[6:6] ([]) b[5:6] (['f'])
['a', 'b', 'x', 'b', 'd', 'f']
['a', 'b', 'y', 'c', 'd', 'f']
False

问题出在哪里?

我想我知道原因了:由
s.get_opcodes()
返回的5元组在容器的初始状态下是有效的,也就是说,如果对象发生更改,它们必须进行调整:这就是delete操作的情况,特别是,它会更改索引(这就是为什么
'x'
不会变成
'y'

就我所见,删除操作是唯一更改索引的操作,因此我将用标记(我使用了“#”)替换已删除的项,并在最后将其删除:

>>> c = a[:]
>>> for tag, i1, i2, j1, j2 in s.get_opcodes():
    print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % 
    (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2]))
    if tag == "delete":
        c[i1:i2] = ['#' for i in range(i1, i2)]
    elif tag == "replace":
        c[i1:i2] = b[j1:j2]
    elif tag == "insert":
        c[i1:i1] = b[j1:j2]
    print c


 delete a[0:1] (['q']) b[0:0] ([])
['#', 'a', 'b', 'x', 'c', 'd']
  equal a[1:3] (['a', 'b']) b[0:2] (['a', 'b'])
['#', 'a', 'b', 'x', 'c', 'd']
replace a[3:4] (['x']) b[2:3] (['y'])
['#', 'a', 'b', 'y', 'c', 'd']
  equal a[4:6] (['c', 'd']) b[3:5] (['c', 'd'])
['#', 'a', 'b', 'y', 'c', 'd']
 insert a[6:6] ([]) b[5:6] (['f'])
['#', 'a', 'b', 'y', 'c', 'd', 'f']
>>> c = [i for i in c if i != '#']
>>> c
['a', 'b', 'y', 'c', 'd', 'f']
>>> 

所有的动作都会改变索引。当我要做的时候,我必须计算变化:

a = [x for x in "abyffgh fg99"]
b = [x for x in "999aby99ff9h9"]
c = a[:]

s = SequenceMatcher(None, a, b)

i = 0
for tag, i1, i2, j1, j2 in s.get_opcodes():
    print ("%7s a[%d:%d] (%s) b[%d:%d] (%s) c[%d:%d] (%s)" % 
    (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2], i1, i2, c[i1 + i:i2 + i]))
    if tag == "delete":
        del c[i1 + i:i2 + i]
        i -= i2 - i1
    elif tag == "replace":
        c[i1 + i:i2 + i] = b[j1:j2]
        i -= i2 - i1 - j2 + j1
    elif tag == "insert":
        c[i1 + i:i2 + i] = b[j1:j2]
        i += j2 - j1
    print c
    print i
print c
print b
print c == b
a == b
输出:

['9', '9', '9', 'a', 'b', 'y', '9', '9', 'f', 'f', '9', 'h', ' ', 'f', 'g', '9', '9']
5
 delete a[7:10] ([' ', 'f', 'g']) b[12:12] ([]) c[7:10] ([' ', 'f', 'g'])
['9', '9', '9', 'a', 'b', 'y', '9', '9', 'f', 'f', '9', 'h', '9', '9']
1
  equal a[10:11] (['9']) b[12:13] (['9']) c[10:11] (['h'])
['9', '9', '9', 'a', 'b', 'y', '9', '9', 'f', 'f', '9', 'h', '9', '9']
1
 delete a[11:12] (['9']) b[13:13] ([]) c[11:12] (['9'])
['9', '9', '9', 'a', 'b', 'y', '9', '9', 'f', 'f', '9', 'h', '9']
-1
['9', '9', '9', 'a', 'b', 'y', '9', '9', 'f', 'f', '9', 'h', '9']
['9', '9', '9', 'a', 'b', 'y', '9', '9', 'f', 'f', '9', 'h', '9']
True

您希望它们是-因为?对于上下文,这与difflib.SequenceMatcher.get_操作码的python文档中的示例非常相似:在这个示例中,唯一更改索引的是
delete
操作。但在另一个示例中,我尝试了
replace
操作将更少的项替换为更多的项。这也会移动索引。等等。我必须数一数变化。你完全是对的,我错了!但我想那样你会明白的。