Python 按单词匹配更改,而不是按字符匹配
我正在使用Python 按单词匹配更改,而不是按字符匹配,python,string,python-3.x,diff,difflib,Python,String,Python 3.x,Diff,Difflib,我正在使用difflib的SequenceMatcher来获取操作码(),然后用css突出显示更改,以创建某种webdiff 首先,我设置了 Min Delta ,所以我认为如果整个字符串中只有3个或更多个字符不同,则两个字符串是不同的( deltaΔ/CODE)是指一个真实的、遇到的delta,它总结了所有字符的变化): matcher=SequenceMatcher(源代码、差异代码) 最小增量=3 增量=0 对于matcher.get_操作码()中的标记i1、i2、j1、j2: 如果标记=
difflib
的SequenceMatcher
来获取操作码()
,然后用css
突出显示更改,以创建某种webdiff
首先,我设置了<代码> Min Delta ,所以我认为如果整个字符串中只有3个或更多个字符不同,则两个字符串是不同的(<代码> deltaΔ/CODE)是指一个真实的、遇到的delta,它总结了所有字符的变化):
matcher=SequenceMatcher(源代码、差异代码)
最小增量=3
增量=0
对于matcher.get_操作码()中的标记i1、i2、j1、j2:
如果标记==“相等”:
继续#这里没有要捕获的内容
elif标记==“删除”:
如果源字符串[i1:i2].isspace():
继续#对空格不可知
其他:
delta+=(i2-i1)#删除i2-i1字符
elif标记==“替换”:
如果源字符串[i1:i2].isspace()或差异字符串[j1:j2].isspace():
继续#对空格不可知
其他:
增量+=(i2-i1)#替换i2-i1字符
elif标记==“插入”:
如果差异[j1:j2].isspace():
继续#对空格不可知
其他:
增量+=(j2-j1)#插入j2-j1字符
如果(增量>最小增量)否则为False,则返回值=True
这有助于我确定两个字符串是否真的不同。效率不是很高,但我认为没有比这更好的了
然后,我以相同的方式为两个字符串之间的差异着色:
匹配器中标记i1、i2、j1、j2的获取操作码()
如果标记==“相等”:
#忙碌的字符串,插入到s和彩色
elif标记==“删除”:
# ...
返回值=旧字符串,新字符串
结果看起来很难看(蓝色表示已替换,绿色表示新,红色表示已删除,不表示相等):
所以发生这种情况是因为SequenceMatcher
匹配每个字符。但是我想让它匹配每一个单词(可能还有它们周围的空格),或者更吸引人的东西,因为正如你在截图上看到的,第一本书实际上被移动到了第四个位置
在我看来,可以使用SequenceMatcher
的isjunk
和autojunk
参数来做一些事情,但我不知道如何编写lambda
以达到我的目的
因此,我有两个问题:
get_opcodes()
和SequenceMatcher
?如果没有,可以用什么来代替minu delta
摆脱肮脏的黑客行为,并且只要至少有一个单词不同,就返回True
,对吗SequenceMatcher
可以接受str
列表作为输入
您可以先将输入拆分为单词,然后使用SequenceMatcher
帮助您区分单词。然后,你的彩色差异将是由文字,而不是由字符
您还可以按直线、书本或线段进行区分。您只需要准备一个函数,该函数可以将整个文章字符串预处理为所需的diff块
例如:
- 要按行区分-您可能可以使用
splitlines()
- 按书本区分-您可能可以实现一个函数,去掉
,1.
2.
- 要按段区分-您可以这样插入API
。然后你的颜色将被分段([book_1,author_1,year_1,book_2,author_2,…],[book_1,author_1,year_1,book_2,author_2,…)
True if delta>min_delta else False
与简单的delta>min_delta
完全相同吗?说得好!当我在编写代码时,这只是一种为我自己添加更多清晰性的方法。我通常在之后重构代码,以消除不必要的冗长和内联一些操作。这次我忘了在一个示例中这样做。请不要滥用内联代码格式来突出显示不是代码的内容(例如类/模块/函数名、小代码示例等)或按字面意思编写的内容(例如,应完全按照显示内容编写的唯一标识符)。要强调其他类型的内容,请使用斜体(*斜体*)或粗体(**粗体**)。
>>> def my_get_opcodes(a, b):
... s = SequenceMatcher(None, a, b)
... for tag, i1, i2, j1, j2 in s.get_opcodes():
... print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(
... tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))
...
>>> my_get_opcodes("qabxcd", "abycdf")
delete a[0:1] --> b[0:0] 'q' --> ''
equal a[1:3] --> b[0:2] 'ab' --> 'ab'
replace a[3:4] --> b[2:3] 'x' --> 'y'
equal a[4:6] --> b[3:5] 'cd' --> 'cd'
insert a[6:6] --> b[5:6] '' --> 'f'
# This is the bad result you currently have.
>>> my_get_opcodes("one two three\n", "ore tree emu\n")
equal a[0:1] --> b[0:1] 'o' --> 'o'
replace a[1:2] --> b[1:2] 'n' --> 'r'
equal a[2:5] --> b[2:5] 'e t' --> 'e t'
delete a[5:10] --> b[5:5] 'wo th' --> ''
equal a[10:13] --> b[5:8] 'ree' --> 'ree'
insert a[13:13] --> b[8:12] '' --> ' emu'
equal a[13:14] --> b[12:13] '\n' --> '\n'
>>> my_get_opcodes("one two three\n".split(), "ore tree emu\n".split())
replace a[0:3] --> b[0:3] ['one', 'two', 'three'] --> ['ore', 'tree', 'emu']
# This may be the result you want.
>>> my_get_opcodes("one two emily three ha\n".split(), "ore tree emily emu haha\n".split())
replace a[0:2] --> b[0:2] ['one', 'two'] --> ['ore', 'tree']
equal a[2:3] --> b[2:3] ['emily'] --> ['emily']
replace a[3:5] --> b[3:5] ['three', 'ha'] --> ['emu', 'haha']
# A more complicated example exhibiting all four kinds of opcodes.
>>> my_get_opcodes("one two emily three yo right end\n".split(), "ore tree emily emu haha yo yes right\n".split())
replace a[0:2] --> b[0:2] ['one', 'two'] --> ['ore', 'tree']
equal a[2:3] --> b[2:3] ['emily'] --> ['emily']
replace a[3:4] --> b[3:5] ['three'] --> ['emu', 'haha']
equal a[4:5] --> b[5:6] ['yo'] --> ['yo']
insert a[5:5] --> b[6:7] [] --> ['yes']
equal a[5:6] --> b[7:8] ['right'] --> ['right']
delete a[6:7] --> b[8:8] ['end'] --> []