为Python 2/3实现Google的DiffMatchPatch API

时间:2013-04-18 06:22:19

标签: python diff

我想用Google's Diff Match Patch APIs在Python中编写一个简单的diff应用程序。 我是Python的新手,所以我想要一个如何使用Diff Match Patch API进行语义比较两段文本的例子。我不太清楚如何使用diff_match_patch.py文件以及从中导入的内容。非常感谢帮助!

此外,我尝试过使用difflib,但我发现它对于比较多变的句子无效。我正在使用ubuntu 12.04 x64。

1 个答案:

答案 0 :(得分:19)

Google的diff-match-patch API对于它实现的所有语言都是相同的(Java,JavaScript,Dart,C ++,C#,Objective C,Lua和Python 2.x或python 3.x)。因此,通常可以使用除了一种目标语言之外的语言的样本片段来确定各种差异/匹配/补丁任务所需的特定API调用。

在简单的“语义”比较的情况下,这就是你需要的

import diff_match_patch

textA = "the cat in the red hat"
textB = "the feline in the blue hat"

#create a diff_match_patch object
dmp = diff_match_patch.diff_match_patch()

# Depending on the kind of text you work with, in term of overall length
# and complexity, you may want to extend (or here suppress) the
# time_out feature
dmp.Diff_Timeout = 0   # or some other value, default is 1.0 seconds

# All 'diff' jobs start with invoking diff_main()
diffs = dmp.diff_main(textA, textB)

# diff_cleanupSemantic() is used to make the diffs array more "human" readable
dmp.diff_cleanupSemantic(diffs)

# and if you want the results as some ready to display HMTL snippet
htmlSnippet = dmp.diff_prettyHtml(diffs)


关于“语义”处理的一个词:差异匹配补丁
请注意,这样的处理对于向人类观察者呈现差异是有用的,因为它倾向于通过避免文本的非相关重新同步来产生较短的差异列表(例如,当两个不同的词恰好在其中间具有共同的字母时)。然而,所产生的结果远非完美,因为这种处理只是基于差异和表面图案等的长度的简单启发式,而不是基于词典和其他语义级设备的实际NLP处理。
例如,上面使用的textAtextB值会为diffs数组生成以下“before-and-after-diff_cleanupSemantic”值

[(0, 'the '), (-1, 'cat'), (1, 'feline'), (0, ' in the '), (-1, 'r'), (1, 'blu'), (0, 'e'), (-1, 'd'), (0, ' hat')]
[(0, 'the '), (-1, 'cat'), (1, 'feline'), (0, ' in the '), (-1, 'red'), (1, 'blue'), (0, ' hat')]

尼斯!红色和蓝色共有的字母'e'使diff_main()看到文本的这个区域为四个编辑,但cleanupSemantic()只修改了两个编辑,很好地挑出了不同的sems'blue'和'红”。

但是,如果我们有,例如<​​/ p>

textA = "stackoverflow is cool"
textb = "so is very cool"

生成的前/后数组是:

[(0, 's'), (-1, 'tack'), (0, 'o'), (-1, 'verflow'), (0, ' is'), (1, ' very'), (0, ' cool')]
[(0, 's'), (-1, 'tackoverflow is'), (1, 'o is very'), (0, ' cool')]

这表明与之前的相比,之后所谓的语义上改进的可能会被过度“折磨”。请注意,例如,前导's如何保持匹配,以及添加的'非常'单词如何与'酷'表达的部分混合。理想情况下,我们可能会期待像

这样的东西
[(-1, 'stackoverflow'), (1, 'so'), (0, ' is '), (-1, 'very'), (0, ' cool')]