Python - 两个字符串之间的区别

use*_*682 63 python string diff python-3.x

我想在列表中存储很多单词.其中许多词语非常相似.例如,我有话afrykanerskoj?zyczny和许多类似的话afrykanerskoj?zycznym,afrykanerskoj?zyczni,nieafrykanerskoj?zyczni.什么是有效(快速和给予小差异大小)解决方案,以找到两个字符串之间的差异,并从第一个字符串恢复第二个字符串和差异?

daw*_*awg 86

您可以在difflib模块中使用ndiff来执行此操作.它具有将一个字符串转换为另一个字符串所需的所有信息.

一个简单的例子:

import difflib

cases=[('afrykanerskoj?zyczny', 'afrykanerskoj?zycznym'),
       ('afrykanerskoj?zyczni', 'nieafrykanerskoj?zyczni'),
       ('afrykanerskoj?zycznym', 'afrykanerskoj?zyczny'),
       ('nieafrykanerskoj?zyczni', 'afrykanerskoj?zyczni'),
       ('nieafrynerskoj?zyczni', 'afrykanerskojzyczni'),
       ('abcdefg','xac')] 

for a,b in cases:     
    print('{} => {}'.format(a,b))  
    for i,s in enumerate(difflib.ndiff(a, b)):
        if s[0]==' ': continue
        elif s[0]=='-':
            print(u'Delete "{}" from position {}'.format(s[-1],i))
        elif s[0]=='+':
            print(u'Add "{}" to position {}'.format(s[-1],i))    
    print()      
Run Code Online (Sandbox Code Playgroud)

打印:

afrykanerskoj?zyczny => afrykanerskoj?zycznym
Add "m" to position 20

afrykanerskoj?zyczni => nieafrykanerskoj?zyczni
Add "n" to position 0
Add "i" to position 1
Add "e" to position 2

afrykanerskoj?zycznym => afrykanerskoj?zyczny
Delete "m" from position 20

nieafrykanerskoj?zyczni => afrykanerskoj?zyczni
Delete "n" from position 0
Delete "i" from position 1
Delete "e" from position 2

nieafrynerskoj?zyczni => afrykanerskojzyczni
Delete "n" from position 0
Delete "i" from position 1
Delete "e" from position 2
Add "k" to position 7
Add "a" to position 8
Delete "?" from position 16

abcdefg => xac
Add "x" to position 0
Delete "b" from position 2
Delete "d" from position 4
Delete "e" from position 5
Delete "f" from position 6
Delete "g" from position 7
Run Code Online (Sandbox Code Playgroud)

  • +1 Python有*所以*许多有用的模块.我似乎每天都在学习新的东西. (9认同)

小智 14

我喜欢ndiff的答案,但是如果你想将它全部吐入只有变化的列表中,你可以做类似的事情:

import difflib

case_a = 'afrykbnerskoj?zyczny'
case_b = 'afrykanerskoj?zycznym'

output_list = [li for li in difflib.ndiff(case_a, case_b) if li[0] != ' ']
Run Code Online (Sandbox Code Playgroud)

  • 这正是我在Google上搜索的内容.一个快速注释,@ Eric,你的变量与今天20180905所示的不匹配.要么1)如果li [0]将最后一行更改为`output_list = [li for list in list(difflib.ndiff(case_a,case_b)) ]!='']`或2)将字符串变量的名称更改为`case_a - > a`和`case_b - > b`.干杯! (3认同)
  • 显示命令的输出可能也会有所帮助:`>>> output_list`; #result#`['-b','+ a','+ m']` (2认同)
  • `if not li.startswith(' ')` 相当于 `if li[0] != ' '` 有些人可能会发现它更易读。甚至 `if item.startswith(('-', '+', ))` (2认同)
  • @Nathan,你不能对评论投反对票,虽然你认为列表没有开头是正确的,但你已经完全搞砸了类型。`li` 是一个字符串,而不是列表,并且字符串至少从 2012 年起就有了 `startswith()`。字符串可以像数组一样进行索引,因为字符串本质上是一个美化的 `unsigned (w)char[] `,这实际上是一个数组。尝试运行代码 - `output_list = [li for li in difflib.ndiff(case_a, case_b) if not li.startswith(' ')]` 在 3.9 上对我来说效果很好 (2认同)

per*_*eal 5

您可以查看正则表达式模块(模糊部分)。我不知道您是否可以获得实际差异,但至少您可以指定允许的不同类型更改的数量,例如插入、删除和替换:

import regex
sequence = 'afrykanerskojezyczny'
queries = [ 'afrykanerskojezycznym', 'afrykanerskojezyczni', 
            'nieafrykanerskojezyczni' ]
for q in queries:
    m = regex.search(r'(%s){e<=2}'%q, sequence)
    print 'match' if m else 'nomatch'
Run Code Online (Sandbox Code Playgroud)