Разделите буквы разницей двух строк

Это поведение, которое я хочу:

a: IGADKYFHARGNYDAA c: KGADKYFHARGNYEAA 2 difference(s). 

15 Solutions collect form web for “Разделите буквы разницей двух строк”

Я предполагаю, что этот exmaple будет работать для вас в этом конкретном случае без особых сложностей и проблем с совместимостью с вашей версией программного обеспечения на python (до версии 2.7):

 a='IGADKYFHARGNYDAA' b='KGADKYFHARGNYEAA' u=zip(a,b) d=dict(u) x=[] for i,j in d.items(): if i==j: x.append('*') else: x.append(j) print x - a='IGADKYFHARGNYDAA' b='KGADKYFHARGNYEAA' u=zip(a,b) d=dict(u) x=[] for i,j in d.items(): if i==j: x.append('*') else: x.append(j) print x 

Выходы: ['*', 'E', '*', '*', 'K', '*', '*', '*', '*', '*']


С небольшими тиражами вы можете получить то, что хотите … Скажите, если это поможет 🙂


Обновить

Вы также можете использовать это:

 a='IGADKYFHARGNYDAA' b='KGADKYFHARGNYEAA' u=zip(a,b) for i,j in u: if i==j: print i,'--',j else: print i,' ',j - a='IGADKYFHARGNYDAA' b='KGADKYFHARGNYEAA' u=zip(a,b) for i,j in u: if i==j: print i,'--',j else: print i,' ',j 

Выходы:

 IK G -- G A -- A D -- D K -- K Y -- Y F -- F H -- H A -- A R -- R G -- G N -- N Y -- Y DE A -- A A -- A 

Обновление 2

Вы можете изменить код следующим образом:

 y=[] counter=0 for i,j in u: if i==j: print i,'--',j else: y.append(j) print i,' ',j print '\n', y print '\n Length = ',len(y) 

Выходы:

 IK G -- G A -- A D -- D K -- K Y -- Y F -- F H -- H A -- A R -- R G -- G N -- N Y -- Y DE A -- A AX ['K', 'E', 'X'] Length = 3 
 def diff_letters(a,b): return sum ( a[i] != b[i] for i in range(len(a)) ) 

Теория

  1. Итерации по обеим строкам одновременно и сравнение символов.
  2. Сохраните результат с помощью новой строки, добавив либо пробел, либо символ | характер к нему, соответственно. Кроме того, увеличьте целочисленное значение, начиная с нуля для каждого другого символа.
  3. Выведите результат.

Реализация

Вы можете использовать встроенную функцию zip или itertools.izip для одновременной итерации по обеим строкам, в то время как последняя является немного более эффективной в случае огромного ввода. Если строки не имеют одинакового размера, то итерация будет выполняться только для более короткой части. Если это так, вы можете пополнить остальные символом индикации отсутствия соответствия.

 import itertools def compare(string1, string2, no_match_c=' ', match_c='|'): if len(string2) < len(string1): string1, string2 = string2, string1 result = '' n_diff = 0 for c1, c2 in itertools.izip(string1, string2): if c1 == c2: result += match_c else: result += no_match_c n_diff += 1 delta = len(string2) - len(string1) result += delta * no_match_c n_diff += delta return (result, n_diff) 

пример

Вот простой тест, с немного отличающимися вариантами, чем от вашего примера выше. Обратите внимание, что я использовал символ подчеркивания для указания несогласованных символов, чтобы лучше продемонстрировать, как результирующая строка расширяется до размера более длинной строки.

 def main(): string1 = 'IGADKYFHARGNYDAA AWOOH' string2 = 'KGADKYFHARGNYEAA W' result, n_diff = compare(string1, string2, no_match_c='_') print "%d difference(s)." % n_diff print string1 print result print string2 main() 

Вывод:

 niklas@saphire:~/Desktop$ python foo.py 6 difference(s). IGADKYFHARGNYDAA AWOOH _

_

_|___ KGADKYFHARGNYEAA W

У Python есть отличный difflib , который должен обеспечить необходимую функциональность.

Вот пример использования из документации:

 import difflib # Works for python >= 2.1 >>> s = difflib.SequenceMatcher(lambda x: x == " ", ... "private Thread currentThread;", ... "private volatile Thread currentThread;") >>> for block in s.get_matching_blocks(): ... print "a[%d] and b[%d] match for %d elements" % block a[0] and b[0] match for 8 elements a[8] and b[17] match for 21 elements a[29] and b[38] match for 0 elements 

С difflib.ndiff вы можете сделать это в однострочном лайнере, который все еще несколько понятен:

 >>> import difflib >>> a = 'IGADKYFHARGNYDAA' >>> c = 'KGADKYFHARGNYEAA' >>> sum([i[0] != ' ' for i in difflib.ndiff(a, c)]) / 2 2 

( sum работает здесь, потому что, ну, вид True == 1 и False == 0 )

Следующее дает понять, что происходит и почему требуется / 2 :

 >>> [i for i in difflib.ndiff(a,c)] ['- I', '+ K', ' G', ' A', ' D', ' K', ' Y', ' F', ' H', ' A', ' R', ' G', ' N', ' Y', '- D', '+ E', ' A', ' A'] 

Это также хорошо работает, если строки имеют разную длину.

При переходе по одной строке создайте объект-счетчик, который идентифицирует букву, на которой вы находитесь, на каждой итерации. Затем используйте этот счетчик в качестве индекса для ссылки на другую последовательность.

 a = 'IGADKYFHARGNYDAA' b = 'KGADKYFHARGNYEAA' counter = 0 differences = 0 for i in a: if i != b[counter]: differences += 1 counter += 1 

Здесь каждый раз, когда мы сталкиваемся с буквой в последовательности а, которая отличается от буквы в том же положении в последовательности b, мы добавляем 1 к «различиям». Затем мы добавляем 1 к счетчику, прежде чем переместимся на следующую букву.

Мне нравится ответ от Niklas R, но у него есть проблема (в зависимости от ваших ожиданий). Используя ответ со следующими двумя тестовыми примерами:

 print compare('berry','peach') print compare('berry','cherry') 

Мы можем разумно ожидать, что вишня будет больше похожа на ягоды, чем на персик . Тем не менее, мы получаем более низкий разницу между ягодами и персиком , затем ягодными и вишневыми :

 (' | ', 4) # berry, peach (' | ', 5) # berry, cherry 

Это происходит, когда строки более похожи назад, чем вперед. Чтобы продлить ответ от ответа от Niklas R, мы можем добавить вспомогательную функцию, которая возвращает минимальный разность между нормальным (вперед) diff и разностью обратных строк:

 def fuzzy_compare(string1, string2): (fwd_result, fwd_diff) = compare(string1, string2) (rev_result, rev_diff) = compare(string1[::-1], string2[::-1]) diff = min(fwd_diff, rev_diff) return diff 

Повторите следующие тесты:

 print fuzzy_compare('berry','peach') print fuzzy_compare('berry','cherry') 

… и мы получаем

 4 # berry, peach 2 # berry, cherry 

Как я уже сказал, это действительно просто расширяет , а не изменяет ответ Никласа Р.

Если вы просто ищете простую функцию diff (с учетом вышеупомянутой gotcha), то следующее:

 def diff(a, b): delta = do_diff(a, b) delta_rev = do_diff(a[::-1], b[::-1]) return min(delta, delta_rev) def do_diff(a,b): delta = 0 i = 0 while i < len(a) and i < len(b): delta += a[i] != b[i] i += 1 delta += len(a[i:]) + len(b[i:]) return delta 

Тестовые случаи:

 print diff('berry','peach') print diff('berry','cherry') 

Последнее соображение касается самой функции diff при обработке слов различной длины. Существует два варианта:

  1. Рассмотрим разницу между длинами как разностными символами.
  2. Игнорируйте разницу в длине и сравните только кратчайшее слово.

Например:

  • яблоко и яблоки имеют разницу в 1 при рассмотрении всех персонажей.
  • яблоко и яблоки имеют разницу 0 при рассмотрении только кратчайшего слова

Рассматривая только кратчайшее слово, которое мы можем использовать:

 def do_diff_shortest(a,b): delta, i = 0, 0 if len(a) > len(b): a, b = b, a for i in range(len(a)): delta += a[i] != b[i] return delta 

… число итераций продиктовано самым коротким словом, все остальное игнорируется. Или мы можем принимать во внимание разную длину:

 def do_diff_both(a, b): delta, i = 0, 0 while i < len(a) and i < len(b): delta += a[i] != b[i] i += 1 delta += len(a[i:]) + len(b[i:]) return delta 

В этом примере любые оставшиеся символы подсчитываются и добавляются к значению diff. Чтобы проверить обе функции

 print do_diff_shortest('apple','apples') print do_diff_both('apple','apples') 

Вывод:

 0 # Ignore extra characters belonging to longest word. 1 # Consider extra characters. 
 a = "IGADKYFHARGNYDAA" b = "KGADKYFHARGNYEAAXXX" match_pattern = zip(a, b) #give list of tuples (of letters at each index) difference = sum (1 for e in zipped if e[0] != e[1]) #count tuples with non matching elements difference = difference + abs(len(a) - len(b)) #in case the two string are of different lenght, we add the lenght difference 

Вот мое решение аналогичной проблемы, сравнивая две строки на основе представленного здесь решения: https://stackoverflow.com/a/12226960/3542145 .

Поскольку itertools.izip не работал для меня в Python3, я нашел решение, которое вместо этого использует zip-функцию: https://stackoverflow.com/a/32303142/3542145 .

Функция сравнения двух строк:

 def compare(string1, string2, no_match_c=' ', match_c='|'): if len(string2) < len(string1): string1, string2 = string2, string1 result = '' n_diff = 0 for c1, c2 in zip(string1, string2): if c1 == c2: result += match_c else: result += no_match_c n_diff += 1 delta = len(string2) - len(string1) result += delta * no_match_c n_diff += delta return (result, n_diff) 

Настройте две строки для сравнения и вызовите функцию:

 def main(): string1 = 'AAUAAA' string2 = 'AAUCAA' result, n_diff = compare(string1, string2, no_match_c='_') print("%d difference(s)." % n_diff) print(string1) print(result) print(string2) main() 

Что возвращает:

 1 difference(s). AAUAAA 

_|| AAUCAA

  • Потребление памяти в словаре: установить значение Нет или удалить элемент
  • Как создать интернационализированное приложение Google App Engine
  • Получение модуля python -m для работы с модулем, реализованным на C
  • ValueError: символ неподдерживаемого формата '
  • python: как удалить значения из 2 списков на основе того, что находится в 1 списке
  • Несчастливый номер 13
  • Сценарии Python перестали работать с двойным щелчком в Windows
  • Почему вы не должны использовать os.linesep при редактировании в текстовом режиме?
  •  
    Interesting Posts for Van-Lav

    Настройка Flask-SQLAlchemy для использования нескольких баз данных с Flask-Restless

    Как преобразовать изображение RGB в оттенки серого в Python?

    Скрипт Python, зависающий при работе в фоновом режиме

    Исключительные странные результаты с использованием кривой

    Фильтрация DataFrame Pyspark с помощью SQL-подобной инструкции IN

    Ошибка Pyinstaller для проекта Djnago "ImportError: Нет модуля с именем" django.contrib.admin.apps ""

    Можно ли показать точное положение в Sublime Text 2?

    Как удалить dict из списка с дублирующимися полями в python?

    Правильный способ создания функций, расширяемых пользователем

    Trace Bug, который иногда встречается только в CI

    В чем преимущества использования syslog по сравнению с другими системами ведения журнала?

    UnboundLocalError: локальная переменная 'Core_prices', на которую ссылаются перед назначением

    Найти текущий каталог и каталог файла

    Замораживание программы во время выполнения функции в Tkinter

    Фильтровать внешнюю ссылку внутри строки

    Python - лучший язык программирования в мире.