Извлечь разницу между двумя строками в Java

Привет у меня есть две строки:

    String hear = "Hi My name is Deepak"
            + "\n"
            + "How are you ?"
            + "\n"
            + "\n"
            + "How is everyone";
    String dear = "Hi My name is Deepak"
            + "\n"
            + "How are you ?"
            + "\n"
            + "Hey there \n"
            + "How is everyone";

Я хочу получить то, чего нет в строке прослушивания "Hey There \n". Я нашел метод, но он не работает в этом случае:

static String strDiffChop(String s1, String s2) {
    if (s1.length() > s2.length()) {
        return s1.substring(s2.length() - 1);
    } else if (s2.length() > s1.length()) {
        return s2.substring(s1.length() - 1);
    } else {
        return "";
    }
}

Может ли кто-нибудь помочь?

9 ответов

Google-Diff-матч-патч

Библиотеки Diff Match и Patch предлагают надежные алгоритмы для выполнения операций, необходимых для синхронизации простого текста.

Diff:

Сравните два блока простого текста и эффективно верните список отличий.

Матч:

По заданной строке поиска найдите лучшее нечеткое совпадение в блоке простого текста. Взвешены как по точности, так и по местоположению.

Patch:

Примените список исправлений к простому тексту. Приложите все усилия, чтобы применить исправление, даже если основной текст не совпадает.

В настоящее время доступны на Java, JavaScript, Dart, C++, C#, Objective C, Lua и Python. Независимо от языка каждая библиотека имеет одинаковый API и одинаковые функциональные возможности. Все версии также имеют комплексные тестовые комплекты.

Есть вики-страница Line или word diffs, которая описывает, как делать построчные сравнения.

Можно использовать StringUtils от Apache Commons. Вот API StringUtils.

public static String difference(String str1, String str2) {
    if (str1 == null) {
        return str2;
    }
    if (str2 == null) {
        return str1;
    }
    int at = indexOfDifference(str1, str2);
    if (at == -1) {
        return EMPTY;
    }
 return str2.substring(at);
}
public static int indexOfDifference(String str1, String str2) {
    if (str1 == str2) {
        return -1;
    }
    if (str1 == null || str2 == null) {
        return 0;
    }
    int i;
    for (i = 0; i < str1.length() && i < str2.length(); ++i) {
        if (str1.charAt(i) != str2.charAt(i)) {
            break;
        }
    }
    if (i < str2.length() || i < str1.length()) {
        return i;
    }
    return -1;
}

Я использовал StringTokenizer, чтобы найти решение. Ниже приведен фрагмент кода

public static List<String> findNotMatching(String sourceStr, String anotherStr){
    StringTokenizer at = new StringTokenizer(sourceStr, " ");
    StringTokenizer bt = null;
    int i = 0, token_count = 0;
    String token = null;
    boolean flag = false;
    List<String> missingWords = new ArrayList<String>();
    while (at.hasMoreTokens()) {
        token = at.nextToken();
        bt = new StringTokenizer(anotherStr, " ");
        token_count = bt.countTokens();
        while (i < token_count) {
            String s = bt.nextToken();
            if (token.equals(s)) {
                flag = true;
                break;
            } else {
                flag = false;
            }
            i++;
        }
        i = 0;
        if (flag == false)
            missingWords.add(token);
    }
    return missingWords;
}

Преобразовать строку в списки, а затем использовать следующий метод для получения результата Как удалить общие значения из списка двух массивов

Если вы предпочитаете не использовать внешнюю библиотеку, вы можете использовать следующий фрагмент кода Java для эффективного вычисления разницы:

/**
 * Returns an array of size 2. The entries contain a minimal set of characters
 * that have to be removed from the corresponding input strings in order to
 * make the strings equal.
 */
public String[] difference(String a, String b) {
    return diffHelper(a, b, new HashMap<>());
}

private String[] diffHelper(String a, String b, Map<Long, String[]> lookup) {
    return lookup.computeIfAbsent(((long) a.length()) << 32 | b.length(), k -> {
        if (a.isEmpty() || b.isEmpty()) {
            return new String[]{a, b};
        } else if (a.charAt(0) == b.charAt(0)) {
            return diffHelper(a.substring(1), b.substring(1), lookup);
        } else {
            String[] aa = diffHelper(a.substring(1), b, lookup);
            String[] bb = diffHelper(a, b.substring(1), lookup);
            if (aa[0].length() + aa[1].length() < bb[0].length() + bb[1].length()) {
                return new String[]{a.charAt(0) + aa[0], aa[1]};
            } else {
                return new String[]{bb[0], b.charAt(0) + bb[1]};
            }
        }
    });
}

Этот подход использует динамическое программирование. Он пробует все комбинации методом грубой силы, но запоминает уже вычисленные подстроки и, следовательно, работает в O(n^2).

Примеры:

String hear = "Hi My name is Deepak"
        + "\n"
        + "How are you ?"
        + "\n"
        + "\n"
        + "How is everyone";
String dear = "Hi My name is Deepak"
        + "\n"
        + "How are you ?"
        + "\n"
        + "Hey there \n"
        + "How is everyone";
difference(hear, dear); // returns {"","Hey there "}

difference("Honda", "Hyundai"); // returns {"o","yui"}

difference("Toyota", "Coyote"); // returns {"Ta","Ce"}

Вы должны использовать StringUtils от Apache Commons

Я искал какое-то решение, но не смог найти то, что мне нужно, поэтому я создал вспомогательный класс для сравнения двух версий текста - новой и старой - и получения текста результата с изменениями между тегами - [добавлено] и [удалено]. Его можно легко заменить на выбранный вами маркер вместо этих тегов, например: HTML-тег. строка-версия-сравнение

Любые комментарии будут оценены.

* он может не работать с длинным текстом из-за большей вероятности найти те же фразы, что и удаленные.

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

Он использует минимальное расстояние редактирования (подход рекурсии). Вы можете использовать Dp, если хотите.

      import java.util.concurrent.atomic.AtomicInteger;

// A Naive recursive Java program to find minimum number
// operations to convert str1 to str2
class JoveoTest {
    static int min(int x, int y, int z)
    {
        if (x <= y && x <= z)
            return x;
        if (y <= x && y <= z)
            return y;
        else
            return z;
    }

    static int editDist(String str1, String str2, int m,
                        int n,StringBuilder str)
    {
        if (m == 0) {
            StringBuilder myStr1=new StringBuilder();
            myStr1.append("+"+str2);
            myStr1.reverse();
            str=myStr1;
            return n;
        }
        if (n == 0){
            StringBuilder myStr1=new StringBuilder();
            myStr1.append("-"+str1);
            myStr1.reverse();
            str=myStr1;
            return m;
        }
        if (str1.charAt(m - 1) == str2.charAt(n - 1))
            return editDist(str1, str2, m - 1, n - 1,str);
        
        StringBuilder myStr1=new StringBuilder();
        StringBuilder myStr2=new StringBuilder();
        StringBuilder myStr3=new StringBuilder();
        int insert= editDist(str1, str2, m, n - 1,myStr1);

        int remove=editDist(str1, str2, m - 1, n,myStr2);

        int replace=editDist(str1, str2, m - 1, n-1,myStr3);

        if(insert<remove&&insert<replace){
            myStr1.insert(0,str2.charAt(n-1)+"+");
            str.setLength(0);
            str.append(myStr1);
        }
        else if(remove<insert&&remove<replace){
            myStr2.insert(0,str2.charAt(m-1)+"-");
            str.setLength(0);
            str.append(myStr2);
        }
        else{
            myStr3.insert(0,str2.charAt(n-1)+"+"+str1.charAt(m-1)+"-");
            str.setLength(0);
            str.append(myStr3);
        }

        return 1+min(insert,remove,replace);

    }

    // Driver Code
    public static void main(String args[])
    {
        String str1 = "sunday";
        String str2 = "saturday";
        StringBuilder ans=new StringBuilder();
        System.out.println(editDist(
                str1, str2, str1.length(), str2.length(),ans ));
        System.out.println(ans.reverse().toString());
    }
}

3

+ а + т-п + г

Что насчет этого фрагмента?

public static void strDiff(String hear, String dear){
    String[] hr = dear.split("\n");
    for (String h : hr) {
        if (!hear.contains(h)) {
            System.err.println(h);
        }
    }
}
Другие вопросы по тегам