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


86

我想在列表中存储很多单词。这些词中有许多非常相似。例如,我有话afrykanerskojęzyczny和许多类似的话afrykanerskojęzycznymafrykanerskojęzyczninieafrykanerskojęzyczni。找到两个字符串之间的差异并从第一个字符串和diff还原第二个字符串的有效(快速且具有较小差异大小的)解决方案是什么?


1
“从第一个字符串和差异中恢复第二个字符串”
2013年

2
我相信他的意思是“使第二个字符串与第一个相同”。
Elias Benevedes

1
@EliasBenevedes,完全是:)。
user2626682

1
您是否正在寻找类似的东西difflib?如果是这样,见,例如,stackoverflow.com/questions/774316/...
托雷克

Answers:


109

您可以在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()      

印刷品:

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

14
+1 Python有这么多有用的模块。看来我每天都在学习新的知识。
arshajii

1
这是手动解决差异。当然,使用difflib.restore
dawg

谢谢!但是我不确定这是否可以提高内存效率。列表(difflib.ndiff(“afrykanerskojęzyczny”,“nieafrykanerskojęzyczny”))['+ n','+ i','+ e','a','f','r','y','k' ,'a','n','e','r','s','k','o','j','ę','z','y','c',' z','n','y']
user2626682 2013年

ndiff是一个生成器,因此内存效率很高。您正在调用list它,它将单独生成的字符比较转换为它们的完整列表。如果不调用list它,一次只能有几个内存。
dawg

1
同样适用于Python 2(对我而言),我建议使用特定的来源和特定的输出来问一个问题。我无法在注释中调试...
dawg

24

我喜欢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] != ' ']

3
这就是我在Google上搜索的目的。快速说明@Eric,您的变量与今天显示的不匹配,即20180905。要么1)将最后一行更改为,output_list = [li for li in list(difflib.ndiff(case_a,case_b)) if li[0] != ' ']要么2)将字符串变量的名称更改为case_a -> acase_b -> b。干杯!
bballdave025 '18

3
这也可能是有帮助的,以显示你的命令的输出:>>> output_list; #result#['- b', '+ a', '+ m']
bballdave025

2
if not li.startswith(' ')if li[0] != ' 'Some的等效词,可能会更清晰。甚至if item.startswith(('-', '+', ))
dmmfll

@DMfll Downvote。列表startswith()从python开始没有3.7.4
内森(Nathan)

3

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

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'

3

您要的是一种特殊的压缩形式。 xdelta3是为这种特定类型的压缩而设计的,并且有一个python绑定,但是您可能可以直接使用zlib逃脱。你想使用zlib.compressobj,并zlib.decompressobjzdict参数设置为你的“基数词”,例如afrykanerskojęzyczny

zdict仅在python 3.3及更高版本中支持警告,如果所有差异都具有相同的“基本词”,则最容易编写代码,这可能是您想要的,也可能不是。


-2

上面我对原始问题的评论的答案使我认为这就是他想要的:

loopnum = 0
word = 'afrykanerskojęzyczny'
wordlist = ['afrykanerskojęzycznym','afrykanerskojęzyczni','nieafrykanerskojęzyczni']
for i in wordlist:
    wordlist[loopnum] = word
    loopnum += 1

这将执行以下操作:

对于单词列表中的每个值,请将单词列表的值设置为原始代码。

您要做的就是将这段代码放在需要更改单词表的位置,确保将需要更改的单词存储在单词表中,并且原始单词正确。

希望这可以帮助!


谢谢,但实际上,我想以记忆有效的方式存储“nieafrykanerskojęzyczni”之类的单词,使用与“afrykanerskojęzyczny”的相似性。
user2626682
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.