来自ndiff
的{{1}}函数允许一个很好的界面来检测线条的差异。当线条足够接近时它做得很好:
difflib
但是当线条太不相似时,不再可能进行丰富的报告:
>>> print '\n'.join(list(ndiff(['foo*'], ['foot'], )))
- foo*
? ^
+ foot
? ^
这是我正在使用的用例,我正在尝试使用>>> print '\n'.join(list(ndiff(['foo'], ['foo*****'], )))
- foo
+ foo*****
(或基础类ndiff
)来强制报告,即使字符串太不相似。< / p>
对于失败的例子,我希望得到如下结果:
Differ
答案 0 :(得分:1)
负责打印上下文的函数(即以?
开头的那些行)是Differ._fancy_replace
。该函数通过检查两条线是否相等至少75%来工作(参见cutoff
变量)。不幸的是,75%的截止值是硬编码的,无法改变。
我可以建议的是继承Differ
并提供_fancy_replace
的版本,它只是忽略了截止。这是:
from difflib import Differ, SequenceMatcher
class FullContextDiffer(Differ):
def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
"""
Copied and adapted from https://github.com/python/cpython/blob/3.6/Lib/difflib.py#L928
"""
best_ratio = 0
cruncher = SequenceMatcher(self.charjunk)
for j in range(blo, bhi):
bj = b[j]
cruncher.set_seq2(bj)
for i in range(alo, ahi):
ai = a[i]
if ai == bj:
continue
cruncher.set_seq1(ai)
if cruncher.real_quick_ratio() > best_ratio and \
cruncher.quick_ratio() > best_ratio and \
cruncher.ratio() > best_ratio:
best_ratio, best_i, best_j = cruncher.ratio(), i, j
yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
aelt, belt = a[best_i], b[best_j]
atags = btags = ""
cruncher.set_seqs(aelt, belt)
for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
la, lb = ai2 - ai1, bj2 - bj1
if tag == 'replace':
atags += '^' * la
btags += '^' * lb
elif tag == 'delete':
atags += '-' * la
elif tag == 'insert':
btags += '+' * lb
elif tag == 'equal':
atags += ' ' * la
btags += ' ' * lb
else:
raise ValueError('unknown tag %r' % (tag,))
yield from self._qformat(aelt, belt, atags, btags)
yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
这是一个如何运作的例子:
a = [
'foo',
'bar',
'foobar',
]
b = [
'foo',
'bar',
'barfoo',
]
print('\n'.join(FullContextDiffer().compare(a, b)))
# Output:
#
# foo
# bar
# - foobar
# ? ---
#
# + barfoo
# ? +++
答案 1 :(得分:0)
这里你想要做的似乎不是跨多行比较,而是跨越字符串。然后你可以直接传递你的字符串,没有列表,你应该得到一个接近你正在寻找的行为。
>>> print ('\n'.join(list(ndiff('foo', 'foo*****'))))
f
o
o
+ *
+ *
+ *
+ *
+ *
即使输出格式不是您要查找的格式,它也会封装正确的信息。我们可以使输出适配器给出正确的格式。
def adapter(out):
chars = []
symbols = []
for c in out:
chars.append(c[2])
symbols.append(c[0])
return ''.join(chars), ''.join(symbols)
这可以这样使用。
>>> print ('\n'.join(adapter(ndiff('foo', 'foo*****'))))
foo*****
+++++