首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >难以理解Paul Heckel的Diff算法

难以理解Paul Heckel的Diff算法
EN

Stack Overflow用户
提问于 2017-03-13 00:47:49
回答 2查看 1.5K关注 0票数 5

我一直在看Paul Heckel差分算法,我似乎没有完全理解它。

我复制了步骤1-5,如Python代码所示,但我无法使用算法的最后一步使其显示差异。如果有人解释了Python代码的最后一步,我将不胜感激。

另外,我不完全理解为什么您需要在步骤4和5中引用表行,所以对此进行解释也将是令人惊讶的!

非常感谢

以下是我的当前代码:

代码语言:javascript
复制
def find_diff(current_file_as_list, different_file_as_list):

N = current_file_as_list
O = different_file_as_list

table = {}

OA = []
NA = []
for i in O:
    OA.append(i)
for i in N:
    NA.append(i)

# First pass
i = 0

for line in N:
    if not line in table:
        table[line] = {}
        table[line]["NC"] = 1
    else:
        if table[line]["NC"] == 1:
            table[line]["NC"] = 2
        else:
            table[line]["NC"] = "many"
    NA[i] = table[line]
    i += 1

# second pass
j = 0

for line in O:
    if not line in table:
        table[line] = {}
        table[line]["OC"] = 1
    else:
        if not "OC" in table[line]:
            table[line]["OC"] = 1
        elif table[line]["OC"] == 1:
            table[line]["OC"] = 2
        else:
            table[line]["OC"] = "many"
    table[line]["OLNO"] = j  # Gets overwritten with multiple occurrences.
    # Check to see if this is the intended implementation.
    # Maybe only relevant for "OC" == "NC" == 1
    OA[j] = table[line]
    j += 1

# third pass
i = 0

for i in range(0, len(NA)):
    # Check if they appear in both files
    if "OC" in NA[i] and "NC" in NA[i]:
        # Check if they appear exactly once
        if NA[i]["OC"] == NA[i]["NC"] == 1:
            olno = NA[i]["OLNO"]
            NA[i], OA[olno] = olno, i
    i += 1

# fourth pass
# ascending
for i in range(0, len(NA)):
    for j in range(0 , len(OA)):
        if NA[i] == OA[j] and i + 1 < len(NA) and j + 1 < len(OA) and NA[i + 1] == OA[j + 1]:
            OA[j + 1] = table[O[i + 1]]
            NA[i + 1] = table[N[j + 1]]

# fifth pass
# descending
for i in range(len(NA) - 1, 0, -1):
    for j in range(len(OA) - 1, 0, -1):
        if NA[i] == OA[j] and i - 1 > 0 and j - 1 > 0 and NA[i - 1] == OA[j - 1]:
            OA[j - 1] = table[O[i - 1]]
            NA[i - 1] = table[N[j - 1]]

# final step implementation should go here but I'm not sure how to approach it but this is my current attempt (which I am certain is wrong):
k = 0

array = []

for i in range(0, len(NA)):

    if isinstance(NA[i], int):
        array.append("= " + str(N[i]))
        k = NA[i] + 1
    elif isinstance(NA[i], dict):
        array.append("+ " + N[i])

    for j in range(k, len(OA)):
        k = j + 1
        print("j - " + str(j))
        if not isinstance(OA[j], int):
            array.append("- " + O[j])
        else:
            break

您可以将任何两个字符串或字符串列表作为函数的输入。Find_diff(“你好”,“地狱”)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-20 16:31:20

我不知道你在哪里找到这个解释和代码,但它有几个错误。维基百科提供数据比较参考的页面之一是参考保罗的论文,它对理解算法非常有帮助。

首先,据我所知,最后一步的实现是正确的(假设前面的步骤是正确的)。

让我们从一个语法/语言问题开始:也许我遗漏了什么,但我不明白为什么您(以及您链接到的代码)在第三遍中增加了自增量索引i

关于表条目的计数器:在链接代码中有一个注释问题--为什么我们需要2值呢?答案是-我们没有!在论文中,Heckel显式地写道,计数器应该具有的唯一值是0、1和多。您可以看到,我们从未使用或查询计数器的值为2。我猜测这个错误来自于用一种比Heckel在编写算法时想到的更灵活的语言实现该算法,因为查询某个特定表条目是否存在计数器就等于查询计数器的值是否为0。

最后,也是最重要的是,这个实现中的第四和第五关是错误的。在这里,我相信文件中的通行证的措辞可能会让人感到困惑,而且编写链接代码的人都错了。你的第二个问题已经暴露了。第四次传递是在NA上按升序进行的,对于每个位置,其值指向OA中的位置(意味着在讨论的实现中是int类型),我们检查两个数组中的下一个位置的值是否指向相同的表条目。如果是这样的话,我们将这些指针替换为彼此的位置(用ints覆盖指针。因此,您的第二个问题是在这里--我们不使用表条目指针)。这样,我们就有了我们在第三次测试中发现的独特的行,作为锚来查找紧跟在它们之后的、并且是它们“块”的一部分但在文件中并不是唯一的未分配的行。同样的情况发生在第五次,但向后,所以相同的行之前的未改变的唯一线将被归类为不变的以及。

下面是我描述的第四和第五关:

代码语言:javascript
复制
# fourth pass
# ascending
for i in range(0, len(NA) - 1):
    if isinstance(NA[i], int) and (NA[i] + 1) < len(OA) and NA[i + 1] == OA[NA[i] + 1]:
        NA[i + 1] = NA[i] + 1
        OA[NA[i] + 1] = i + 1

# fifth pass
# descending
for i in range(len(NA) - 1, 0, -1):
    if isinstance(NA[i], int) and (NA[i] - 1) >= 0 and NA[i - 1] == OA[NA[i] - 1]:
        NA[i - 1] = NA[i] - 1
        OA[NA[i] - 1] = i - 1
票数 5
EN

Stack Overflow用户

发布于 2022-04-14 07:49:41

我一直在寻找同样的问题的解决方案。最后,我在Python中从头开始实现了Heckel的算法。这是Heckel算法前五步的实现第六步的实现(提取差异库)

您还可以在程序中使用米迪夫包来使用Heckel的算法检测具有块运动的文本差异:

代码语言:javascript
复制
from mdiff import HeckelSequenceMatcher

a = ['line1', 'line2', 'line3', 'line4', 'line5']
b = ['line1', 'line3', 'line2', 'line4', 'line6']
sm = HeckelSequenceMatcher(a, b)
opcodes = sm.get_opcodes()

for tag, i1, i2, j1, j2 in opcodes:
    print('{:7}   a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))
代码语言:javascript
复制
equal     a[0:1] --> b[0:1]  ['line1'] --> ['line1']
move      a[1:2] --> b[2:2]  ['line2'] --> []
equal     a[2:3] --> b[1:2]  ['line3'] --> ['line3']
moved     a[1:1] --> b[2:3]         [] --> ['line2']
equal     a[3:4] --> b[3:4]  ['line4'] --> ['line4']
replace   a[4:5] --> b[4:5]  ['line5'] --> ['line6']

此外,包中还有简单的GUI应用程序,允许可视化和测试算法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42755035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档