什么是最好的(基于单词或字符)的差异算法呢?

时间:2011-12-05 20:54:37

标签: ruby string algorithm merge diff

所以,我希望能够在每个单词的基础上找到两个字符串之间的差异(可能比每个字符更快,但是,如果每个字符更快,那么我想这样做)

这是我想要实现的一个例子: 来源文字:

Hello there!

修改后的文字:

Helay scere?

DIFF:

Hel[lo](ay) [th](sc)ere[!](?)
  • 括号内的文字是删除的内容,括号内的文字是添加的内容

使用命令行工具(例如opendiff)有一种超级hackish方式来执行此操作,但它需要在每个字符之间使用换行符,因为opendiff是基于行的。

我正在使用ruby,并且没有找到任何工具来执行此操作......但语言并不是非常重要,因为算法可以非常轻松地移植。

感谢。

5 个答案:

答案 0 :(得分:2)

这是一个红宝石宝石,它会对琴弦进行差异化:http://rubydoc.info/gems/diff-lcs/1.1.3/frames

在此之前,我刚刚做过(在irb中)

require 'rubygems'
require 'diff/lcs'
require 'diff/lcs/array'
require 'diff/lcs/string'

enter image description here

因此,编写插入,内联删除和插入标记的逻辑变得微不足道,这要归功于2D diff变化数组。

虽然我不确定这是否是最佳方式。

答案 1 :(得分:2)

您可能需要查看此内容:http://en.wikipedia.org/wiki/Longest_common_subsequence_problem。实施起来并不难。

答案 2 :(得分:2)

所以你可以重复使用LCS(如上所述)查找所有常用字符串,并从字符串中删除它们,用其他字符串替换它们 - 让我们只说一个“*”。然后,您同时迭代两个字符串,并将公共和不同的背面重新网格化。

实施例

A) Hello there!
B) Helay scere?

LCS detection gives us ["Hel"," ","ere"], and after replacement we have
A) *lo*th*!
B) *ay*sc*?

Now you split on the delimiter ("*") giving you
A) ["lo","th","!"]
B) ["ay","sc","?"]

从这里你只需要进行简单的网格划分。需要注意的一点是,可能存在空条目,例如,如果您在“地狱”和“Hel”上执行此方法,您最终将获得

Common LCS) ["Hel"]
A) ["l"]
B) [""]

meaning your result will be Hel[l]() 

希望这是可以接受的。

答案 3 :(得分:2)

了解https://github.com/pvande/differ。这个宝石做你想要的

答案 4 :(得分:0)

解决方案是找到字符串之间的编辑距离。