Я нахожусь в процессе написания инструмента сравнения текста для сравнения двух похожих файлов исходного кода.
Есть много таких инструментов "diff", но мой должен быть немного улучшен:
Если он обнаружит, что набор строк не совпадает с обеих сторон (т. Е. В обоих файлах), он должен не только выделить эти строки, но и выделить отдельные изменения в этих строках (здесь я называю это сравнение между строками).
Пример моего несколько работающего решения:
альтернативный текст http://files.tempel.org/tmp/diff_example.png
То, что он в настоящее время делает, это берет набор несовпадающих линий и запускает их отдельные символы еще раз через дифференциал, производя розовую подсветку.
Однако второй набор несоответствий, содержащий «оригинал 2», требует дополнительной работы: здесь были добавлены первые две правые строки («добавленная строка a / b»), а третья строка является измененной версией левая сторона. Я хочу, чтобы мое программное обеспечение обнаружило эту разницу между вероятным изменением и новой строкой.
Глядя на этот простой пример, я довольно легко могу обнаружить этот случай:
С таким алгоритмом, как Левенштейн, я мог бы найти, что из всех правых строк в наборе от 3 до 5, строка 5 лучше всего соответствует левой строке 3, поэтому я мог бы вычесть, что строки 3 и 4 справа были добавлены, и выполнить межстрочное сравнение в левой строке 3 и правой строке 5.
Пока все хорошо. Но я все еще застрял в том, как превратить это в более общий алгоритм для этой цели.
В более сложной ситуации набор различных линий может иметь добавленные линии с обеих сторон с несколькими близко совпадающими линиями между ними. Это становится довольно сложным:
Мне бы пришлось сопоставлять не только первую строку слева с лучшей справа, но и наоборот, и так далее со всеми остальными линиями. По сути, я должен сопоставить каждую строку слева со всеми справа. В худшем случае это может создать ровные пересечения, так что уже не так легко понять, какие строки были недавно вставлены, а какие только что изменены (Примечание: я не хочу иметь дело с возможными перемещенными линиями в таком блоке, если только это на самом деле не упростит алгоритм).
Конечно, это никогда не будет идеальным, но я пытаюсь сделать это лучше, чем сейчас. Любые предложения, которые не являются слишком теоретическими, но довольно практичными (я не очень хорошо понимаю абстрактные алгоритмы), приветствуются.
Обновление
Я должен признать, что я даже не понимаю, как работает алгоритм LCS. Я просто передаю ему два массива строк, и получается список последовательностей, которые не совпадают. Я в основном использую код здесь: http://www.incava.org/projects/java/java-diff
Глядя на код, я нахожу одну функцию, равную (), которая отвечает за указание алгоритму, совпадают ли две строки или нет. Исходя из того, что предложил Павел, мне интересно, это место, где я бы внес изменения. Но как? Эта функция возвращает только логическое значение, а не относительное значение, которое может идентифицировать качество соответствия. И я не могу просто использовать фиксированный рацион Левенштейна, который бы решал, считается ли подобная линия по-прежнему равной или нет - мне нужно что-то самоопределяющееся для всего набора рассматриваемых линий.
Итак, что я в основном говорю, так это то, что я до сих пор не понимаю, где бы я применил нечеткое значение, относящееся к относительному сходству линий, которые (точно) не совпадают.