Алгоритм текстового различия

Мне нужен алгоритм, который может сравнивать два текстовых файла и выделять их различие и (даже лучше!) Может вычислить их различие значимым образом (например, два похожих файла должны иметь показатель сходства выше, чем два разных файла, со словом «похожие» определены в обычных условиях). Звучит легко реализовать, но это не так.

Реализация может быть на C# или Python.

Спасибо.

Чтобы быть ясным, вы просите о текстовом или семантическом сходстве?

Torsten Marek 28.09.2008 14:43

Текстовое сходство. Я предположил, что семантическому сходству еще предстоит пройти долгий путь :)

Graviton 28.09.2008 14:53

Это не так уж и сложно. Простая модель набора слов имеет большое значение.

Torsten Marek 28.09.2008 15:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
42
3
17 834
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Посмотрите на дифлиб. (Python)

Это позволит вычислить различия в различных форматах. Затем вы можете использовать размер контекста diff как меру различий между двумя документами?

Если вам нужна более мелкая детализация, чем линии, вы можете использовать расстояние Левенштейна. Расстояние Левенштейна - это прямая мера того, насколько похожи два текста. Вы также можете использовать его для извлечения журналов редактирования и очень детального сравнения, аналогичного тому, что на страницах истории редактирования SO. Однако имейте в виду, что расстояние Левенштейна может потребовать значительных ресурсов процессора и памяти для вычисления, поэтому использование diffflib, как предположил Дуглас Ледер, скорее всего, будет быстрее.

Ср. также этот ответ.

Я думаю, вам нужно поместить ссылку на этот Cf. в конце. :-)

Douglas Leeder 28.09.2008 14:31

Как уже говорилось, используйте difflib. После того, как у вас есть дифференцированный вывод, вы можете найти Расстояние Левенштейна различных строк, чтобы дать «значение» того, насколько они различны.

Базар содержит альтернативный алгоритм различия, называемый терпение (больше информации в комментариях на этой странице), который, как утверждается, лучше, чем традиционный алгоритм сравнения. Файл «Patiencediff.py» в базовом дистрибутиве представляет собой простой интерфейс командной строки.

Могу порекомендовать взглянуть на код и статьи Нила Фрейзера:

Google-diff-match-patch

Currently available in Java, JavaScript, C++ and Python. Regardless of language, each library features the same API and the same functionality. All versions also have comprehensive test harnesses.

Нил Фрейзер: разные стратегии - за теорию и примечания по реализации

Существует ряд показателей расстояния, как упоминалось в парадодже, есть расстояние Левенштейна, но есть также NYSIIS и Soundex. Что касается реализаций Python, я раньше использовал py-editdist и ADVAS. Оба они хороши в том смысле, что вы получаете одно число в качестве результата. Сначала ознакомьтесь с ADVAS, он реализует множество алгоритмов.

Ответ принят как подходящий

В Python есть дифлиб, как предлагали и другие.

difflib предлагает класс SequenceMatcher, который можно использовать для определения коэффициента сходства. Пример функции:

def text_compare(text1, text2, isjunk=None):
    return difflib.SequenceMatcher(isjunk, text1, text2).ratio()

В настоящее время я понимаю, что лучшим решением проблемы сценария кратчайшего редактирования (SES) является метод Майерса "средней змейки" с уточнением линейного пространства Хиршберга.

Алгоритм Майерса описан в:

E. Myers, ``An O(ND) Difference Algorithm and Its Variations,''
Algorithmica 1, 2 (1986), 251-266.

Утилита GNU diff использует алгоритм Майерса.

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

Обратите внимание, что ряд людей цитировал алгоритм расстояния Левенштейна, но он, хотя и легко реализуемый, не является оптимальным решением, поскольку он неэффективен (требует использования, возможно, огромной матрицы n * m) и не предоставляет сценарий редактирования "- последовательность изменений, которые можно использовать для преобразования одной последовательности в другую и наоборот.

Для хорошей реализации Майерса / Хиршберга посмотрите:

http://www.ioplex.com/~miallen/libmba/dl/src/diff.c

Конкретная библиотека, в которой он содержится, больше не поддерживается, но, насколько мне известно, сам модуль diff.c все еще верен.

Майк

Вы можете использовать решение проблемы самой длинной общей подпоследовательности (LCS). См. Также обсуждение возможных способов оптимизации этого решения.

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

У меня есть реализация diff / patch C#, которая позволяет мне взять два файла, предположительно старую и новую версию одного и того же файла, и вычислить «разницу», но не в обычном смысле этого слова. В основном я рассчитываю набор операций, которые я могу выполнить со старой версией, чтобы обновить ее, чтобы она имела то же содержимое, что и новая версия.

Чтобы использовать это для первоначально описанной функциональности, чтобы увидеть, сколько данных было новым, я просто провел операции, и для каждой операции, которая дословно копировалась из старого файла с коэффициентом 0, и для каждой операции, которая вставляла новый текст (распространяется как часть патча, поскольку не встречается в старом файле) имеет 1-фактор. Всем персонажам была предоставлена ​​эта фабрика, которая дала мне в основном длинный список нулей и единиц.

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

Эта реализация также будет обрабатывать случаи, когда в измененный файл были вставлены копии из старого файла не по порядку или даже дубликаты (например, вы копируете часть с начала файла и вставляете ее ближе к низу), поскольку они оба будут копии той же оригинальной детали из старого файла.

Я экспериментировал с взвешиванием копий, так что первая копия засчитывалась как 0, а последующие копии тех же символов имели прогрессивно более высокие коэффициенты, чтобы придать операции копирования / вставки некоторый «новый фактор», но я так и не закончил ее как проект был отменен.

Если вам интересно, мой код diff / patch доступен в моем репозитории Subversion.

Взгляните на модуль Нечеткое. Он имеет быстрые (написанные на C) алгоритмы на основе soundex, NYSIIS и двойного метафона.

Хорошее введение можно найти по адресу: http://www.informit.com/articles/article.aspx?p=1848528

Другие вопросы по теме