【问题标题】:Extract the difference between two strings in Java提取Java中两个字符串之间的差异
【发布时间】:2013-08-20 20:50:26
【问题描述】:

嗨,我有两个字符串:

    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 "";
    }
}

有人可以帮忙吗?

【问题讨论】:

  • 我认为另一种方法可能是根据空间拆分字符串,然后在每个元素上循环?
  • 是的 Nambari,谢谢。这就是我所做的。

标签: java string compare


【解决方案1】:

google-diff-match-patch

Diff Match 和 Patch 库提供了强大的算法来执行同步纯文本所需的操作。

差异:

比较两个纯文本块并有效地返回差异列表。

匹配:

给定一个搜索字符串,在纯文本块中找到它的最佳模糊匹配。对准确性和位置进行加权。

补丁:

将补丁列表应用于纯文本。即使底层文本不匹配,也要尽最大努力应用补丁。

目前可用于 Java、JavaScript、Dart、C++、C#、Objective C、Lua 和 Python。无论使用哪种语言,每个库都具有相同的 API 和相同的功能。所有版本还具有全面的测试工具。

有一个Line or word diffs wiki 页面描述了如何进行逐行差异。

【讨论】:

【解决方案2】:

可以使用Apache Commons 中的StringUtils。这是StringUtils API

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;
}

【讨论】:

    【解决方案3】:

    我已使用 StringTokenizer 来找到解决方案。下面是代码sn-p

    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 语言对象而不是第 3 方依赖项可以简化代码!
    【解决方案4】:

    将字符串转换为列表,然后使用下面的方法得到结果How to remove common values from two array list

    【讨论】:

    • 我拆分其中一个字符串并遍历数组,发现第二个字符串中的不常见。
    【解决方案5】:

    如果您不想使用外部库,可以使用以下 Java sn-p 来有效地计算差异:

    /**
     * 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"}
    

    【讨论】:

    • 所以键是后缀的长度,它是唯一的并且比后缀本身的哈希计算更快......很好。这正是我正在寻找的算法(针对不同的语言)。
    【解决方案6】:

    我一直在寻找一些解决方案,但找不到我需要的解决方案,因此我创建了一个实用程序类,用于比较两个版本的文本 - 新旧 - 并通过标签之间的更改获取结果文本 - [添加] 和 [已删除]。它可以很容易地替换为您选择的荧光笔而不是这个标签,例如:一个 html 标签。 string-version-comparison

    任何 cmets 将不胜感激。

    *它可能不适用于长文本,因为找到与删除相同的短语的可能性更高。

    【讨论】:

      【解决方案7】:

      你应该使用来自 Apache Commons 的 StringUtils

      String diff = StringUtils.difference( "Word", "World" );
      System.out.println( "Difference: " + diff );
      
      
      Difference: ld
      

      来源:https://www.oreilly.com/library/view/jakarta-commons-cookbook/059600706X/ch02s15.html

      【讨论】:

      • 是的,我听说过很多。
      • 我不赞成这个答案,因为没有迹象表明哪个 StringUtils 方法可以完成这项工作,也没有指向文档或代码示例的链接。对于以后来这里的任何人,只是文档中的一个简单示例:StringUtils.difference("ab", "abxyz") = "xyz"
      【解决方案8】:

      我的解决方案是简单的字符串。 您可以通过标记段落中的行来扩展它。

      它使用最小编辑距离(递归方法)。如果您愿意,可以使用 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

      +a+t-n+r

      【讨论】:

        【解决方案9】:

        这个sn-p怎么样?

        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);
                }
            }
        }
        

        【讨论】:

        • @MikeSamuel 发布了正确的解决方案。那确实是一个真正的差异。如果要匹配的文本内容重新排列其行,String.contains() 将失败。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多