【问题标题】:Text difference algorithm文本差异算法
【发布时间】:2008-09-28 10:12:25
【问题描述】:

我需要一种算法,它可以比较两个文本文件并突出它们的差异,并且(甚至更好!)可以以有意义的方式计算它们的差异(比如两个相似文件的相似度分数应该高于两个不同文件的相似度分数,用 word “类似”用正常术语定义)。这听起来很容易实现,但实际上并非如此。

实现可以是c#或python。

谢谢。

【问题讨论】:

  • 澄清一下,你问的是文本相似度还是语义相似度?
  • 文字相似度。我认为语义相似性还有很长的路要走:)
  • 这并不难。一个简单的词袋模型有很长的路要走。

标签: c# python diff


【解决方案1】:

我可以推荐看看 Neil Fraser 的代码和文章:

google-diff-match-patch

目前在 Java 中可用, JavaScript、C++ 和 Python。不管 语言,每个库都具有 相同的 API 和相同的功能。 所有版本也有全面的 测试工具。

Neil Fraser: Diff Strategies - 理论和实现说明

【讨论】:

    【解决方案2】:

    在 Python 中,有 difflib,正如其他人所建议的那样。

    difflib 提供SequenceMatcher 类,可用于为您提供相似率。示例函数:

    def text_compare(text1, text2, isjunk=None):
        return difflib.SequenceMatcher(isjunk, text1, text2).ratio()
    

    【讨论】:

      【解决方案3】:

      看看difflib。 (Python)

      这将计算各种格式的差异。然后,您可以使用上下文差异的大小来衡量两个文档的差异程度?

      【讨论】:

        【解决方案4】:

        我目前的理解是,最短编辑脚本 (SES) 问题的最佳解决方案是采用 Hirschberg 线性空间细化的 Myers“中蛇”方法。

        Myers 算法描述于:

        E.迈尔斯,“一个 O(ND) 差异 算法及其变体,''
        算法 1, 2 (1986), 251-266.

        GNU diff 实用程序使用 Myers 算法。

        您所说的“相似度分数”在文献中称为“编辑距离”,它是将一个序列转换为另一个序列所需的插入或删除次数。

        请注意,许多人引用了 Levenshtein 距离算法,但尽管它很容易实现,但不是最佳解决方案,因为它效率低下(需要使用可能很大的 n*m 矩阵)并且不提供“编辑脚本”是可用于将一个序列转换为另一个序列的编辑序列,反之亦然。

        要获得良好的 Myers / Hirschberg 实现,请查看:

        http://www.ioplex.com/~miallen/libmba/dl/src/diff.c

        其中包含的特定库不再维护,但据我所知 diff.c 模块本身仍然正确。

        迈克

        【讨论】:

          【解决方案5】:

          Bazaar 包含另一种差异算法,称为patience diff(该页面上的 cmets 中有更多信息),据称它比传统的差异算法更好。 bazaar 发行版中的文件 'patiencediff.py' 是一个简单的命令行前端。

          【讨论】:

            【解决方案6】:

            如果您需要比线条更细的粒度,可以使用 Levenshtein 距离。 Levenshtein 距离是衡量两个文本如何相似的直接衡量标准。
            您还可以使用它来提取编辑日志,并且可以进行非常细粒度的差异,类似于 SO 的编辑历史页面上的差异。 请注意,尽管 Levenshtein 距离计算起来可能会占用大量 CPU 和内存,因此正如 Douglas Leder 所建议的,使用 difflib 很可能会更快。

            参照。还有this answer

            【讨论】:

            • 我认为您需要添加指向该 Cf 的链接。在末尾。 :-)
            【解决方案7】:

            有许多距离指标,正如 paradoja 提到的,有 Levenshtein 距离,但也有 NYSIISSoundex。在Python实现方面,我之前使用过py-editdistADVAS。从某种意义上说,两者都很好,因为您可以将一个数字作为分数返回。先看看ADVAS,它实现了一堆算法。

            【讨论】:

              【解决方案8】:

              如上所述,使用 difflib。获得差异输出后,您可能会找到不同字符串的Levenshtein distance,以给出它们之间差异程度的“值”。

              【讨论】:

                【解决方案9】:

                您可以使用solution to the Longest Common Subsequence (LCS) problem。另请参阅有关优化此解决方案的可能方法的讨论。

                【讨论】:

                  【解决方案10】:

                  我为不同的功能采用了一种方法,即计算修改后的文件中有多少新数据,也许对您也有用。

                  我有一个差异/补丁实现 C#,它允许我获取两个文件,大概是同一文件的旧版本和新版本,并计算“差异”,但不是通常意义上的。基本上我计算了一组可以在旧版本上执行的操作,以将其更新为与新版本具有相同的内容。

                  为了将它用于最初描述的功能,查看有多少新数据,我简单地运行了操作,并且对于从旧文件逐字复制的每个操作,具有 0 因子,以及每个操作插入的新文本(作为补丁的一部分分发,因为它没有出现在旧文件中)具有 1 因子。所有字符都被赋予了这个工厂,它基本上给了我一长串 0 和 1 的列表。

                  然后我所要做的就是计算 0 和 1。在您的情况下,在我的实现中,与 0 相比,1 的数量较少意味着文件非常相似。

                  此实现还可以处理修改后的文件从旧文件中乱序插入副本的情况,甚至是重复的(即,您从文件开头复制一部分并将其粘贴到底部附近),因为它们两者都是旧文件中相同原始部分的副本。

                  我尝试过称重副本,以便第一个副本计为 0,并且相同字符的后续副本具有逐渐更高的因子,以便为复制/粘贴操作提供一些“新因子”,但我从未完成它作为项目被废弃了。

                  如果您有兴趣,可以从我的 Subversion 存储库中获得我的差异/补丁代码。

                  【讨论】:

                    【解决方案11】:

                    看看Fuzzy 模块。它具有基于快速(用 C 语言编写)的 soundex、NYSIIS 和双变音位算法。

                    很好的介绍可以在:http://www.informit.com/articles/article.aspx?p=1848528

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2012-09-14
                      • 1970-01-01
                      • 2010-10-22
                      • 1970-01-01
                      • 2023-03-10
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多