Подтвердить что ты не робот

Python - разница между двумя строками

Я хотел бы хранить много слов в списке. Многие из этих слов очень похожи. Например, у меня есть слово afrykanerskojęzyczny и многие слова типа afrykanerskojęzycznym, afrykanerskojęzyczni, nieafrykanerskojęzyczni. Какое эффективное (быстрое и дающее малый размер) решение, чтобы найти разницу между двумя строками и восстановить вторую строку из первой и diff?

4b9b3361

Ответ 1

Вы можете использовать ndiff в модуле difflib для этого. Он имеет всю информацию, необходимую для преобразования одной строки в другую строку.

Простой пример:

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

Ответ 2

Вы можете заглянуть в модуль регулярных выражений (нечеткий раздел). Я не знаю, можете ли вы получить фактические различия, но по крайней мере вы можете указать допустимое количество различных типов изменений, таких как вставка, удаление и замены:

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.decompressobj с параметром zdict, установленным на ваше "базовое слово", например. afrykanerskojęzyczny.

Предостережения zdict поддерживаются только в python 3.3 и более поздних версиях, и проще всего закодировать, если у вас есть одно и то же "базовое слово" для всех ваших различий, которые могут быть или не быть тем, что вы хотите.

Ответ 4

Ответ на мой комментарий выше на оригинальный вопрос заставляет меня думать, что это все, что он хочет:

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

Это сделает следующее:

Для каждого значения в списке слов установите это значение словарного списка в исходный код.

Все, что вам нужно сделать, это поместить этот фрагмент кода, где вам нужно изменить список слов, убедившись, что вы сохранили слова, которые нужно изменить в списке слов, и что исходное слово верное.

Надеюсь, это поможет!

Ответ 5

Мне нравится ответ ndiff, но если вы хотите переплести все это в список только изменений, вы можете сделать что-то вроде:

import difflib

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

output_list = [li for li in list(difflib.ndiff(a,b)) if li[0] != ' ']