【问题标题】:How do I get starting/ending indexes of all differences between two strings in Java?如何获取 Java 中两个字符串之间所有差异的开始/结束索引?
【发布时间】:2016-07-14 14:55:59
【问题描述】:

在 Java 中,我希望获得两个字符串之间差异的所有开始和结束索引的列表。我知道如何获得两个字符串之间第一个差异的起始索引,但我不太清楚如何解决这个问题。

我在 StringUtils 中找到了代码:indexOfDifference(String, String),它获取两个字符串之间第一个差异的起始索引,但我没有看到获取第一个差异的结束索引的方法,我也没有看到一种获取两个字符串之间所有差异的所有其余开始/结束索引的方法。

例如,如果我有这两个字符串: origStr : "你好世界" modifiedStr : "帮助世界23"

我想要原始 strs 和修订 strs 之间的所有差异范围。

任何指导都会非常有帮助。

这是我目前的代码:

import difflib.*;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

public class TestDiffUtils {

    public TestDiffUtils() {

    }

    // Helper method to read the files to compare into memory, convert them to a list of Strings which can be used by the DiffUtils library for comparison
    private static List fileToLines(String filename) {
        List lines = new LinkedList();
        String line;
        try {
            URL path = TestDiffUtils.class.getResource(filename);
            File f = new File(path.getFile());
            BufferedReader in = new BufferedReader(new FileReader(f));
            while ((line = in.readLine()) != null) {
                lines.add(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return lines;
    }

    private static void printUnifiedDiffs(List<String> diffs){
        for(String diff : diffs){
            System.out.println(diff);
        }
    }

    /**
     * Compares two Strings, and returns the index at which the
     * Strings begin to differ.
     *
     * For example,
     * <code>indexOfDifference("i am a machine", "i am a robot") -> 7</code>
     *
     * <pre>
     * StringUtils.indexOfDifference(null, null) = -1
     * StringUtils.indexOfDifference("", "") = -1
     * StringUtils.indexOfDifference("", "abc") = 0
     * StringUtils.indexOfDifference("abc", "") = 0
     * StringUtils.indexOfDifference("abc", "abc") = -1
     * StringUtils.indexOfDifference("ab", "abxyz") = 2
     * StringUtils.indexOfDifference("abcde", "abxyz") = 2
     * StringUtils.indexOfDifference("abcde", "xyz") = 0
     * </pre>
     *
     * @param str1  the first String, may be null
     * @param str2  the second String, may be null
     * @return the index where str2 and str1 begin to differ; -1 if they are equal
     * @since 2.0
     */
    public static int startingIndexOfDifference(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;
    }

    private static void doBasicLineByLineDiff(Boolean doLargeFileTest) {
        String origFileName;
        String revisedFileName;

        if( doLargeFileTest )
        {
            origFileName = "test_large_file.xml";
            revisedFileName = "test_large_file_revised.xml";
        }else{
            origFileName = "originalFile.txt";
            revisedFileName = "revisedFile.txt";
        }

        List<String> originalLines = fileToLines(origFileName);
        List<String> revisedLines = fileToLines(revisedFileName);

        Patch patch = DiffUtils.diff(originalLines, revisedLines);
        List<String> diffs = DiffUtils.generateUnifiedDiff(origFileName, revisedFileName, originalLines, patch, 0);     // 0 = don't show any lines of context around different lines
        List<Delta> deltas = patch.getDeltas();
        for(Delta delta : deltas){
            int diffLine = delta.getOriginal().getPosition()+1;
            System.out.println("[" + diffLine + " : (" + startingIndexOfDifference((String) delta.getOriginal().getLines().get(0), (String) delta.getRevised().getLines().get(0)) + ",<todo-diffEndIndexHere>)]");
        }

        // printUnifiedDiffs(diffs);
    }

    public static void main(String[] args) {
        doBasicLineByLineDiff(false);
    }
}

【问题讨论】:

  • 编辑显示我到目前为止的代码。我可以获得第一个差异的起始索引,但我需要两个字符串之间所有差异的索引范围。
  • 什么是DiffUtils
  • 所以DiffUtils.diff() 采用List&lt;?&gt;,然后用行(List&lt;String&gt;) 调用它以查找行差异。为什么不重用它来查找两行之间的字符差异,即List&lt;Character&gt;?它已经具有识别差异在哪里结束的所有复杂性,并且共同性再次开始,重复。当你已经有一个库可以做到这一点时,不要尝试自己实现。
  • 您至少需要定义字符串中“差异范围”的含义。什么会表明一系列差异的结束,以及下一个差异的开始?您如何考虑插入和删除?

标签: java difference


【解决方案1】:

DiffUtils.diff() 接受 List&lt;?&gt;,然后用行 (List&lt;String&gt;) 调用它以查找行差异。

您可以重复使用它来查找两行之间的字符差异,即List&lt;Character&gt;

它已经具有识别差异在哪里结束的所有复杂性,而共同点又从哪里开始,重复。当你已经有一个库可以做到时,不要尝试自己实现。

【讨论】:

  • 非常感谢。由于 DiffUtils 类中的一些名称,我错过了这个小细节。 Andreas 指出了这一点,有时最简单的解决方案就是最好的解决方案。
猜你喜欢
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
相关资源
最近更新 更多