Java 找出两个字符串之间的差异
假设我有两根长弦。它们几乎是一样的Java 找出两个字符串之间的差异,java,string,comparison,Java,String,Comparison,假设我有两根长弦。它们几乎是一样的 String a = "this is a example" String b = "this is a examp" 上面的代码只是一个例子。实际字符串相当长 问题是一个字符串比另一个字符串多了两个字符 如何检查这两个字符是哪一个 如果不遍历字符串,您只能知道它们是不同的,而不是在哪里-并且只有当它们的长度不同时才能知道。如果你真的需要知道不同的字符是什么,你必须一步一步地通过两个字符串,并在相应的位置比较字符。你可以使用 他们就是这样实施的: publi
String a = "this is a example"
String b = "this is a examp"
上面的代码只是一个例子。实际字符串相当长
问题是一个字符串比另一个字符串多了两个字符
如何检查这两个字符是哪一个 如果不遍历字符串,您只能知道它们是不同的,而不是在哪里-并且只有当它们的长度不同时才能知道。如果你真的需要知道不同的字符是什么,你必须一步一步地通过两个字符串,并在相应的位置比较字符。你可以使用 他们就是这样实施的:
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 == INDEX_NOT_FOUND) {
return EMPTY;
}
return str2.substring(at);
}
public static int indexOfDifference(CharSequence cs1, CharSequence cs2) {
if (cs1 == cs2) {
return INDEX_NOT_FOUND;
}
if (cs1 == null || cs2 == null) {
return 0;
}
int i;
for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
if (cs1.charAt(i) != cs2.charAt(i)) {
break;
}
}
if (i < cs2.length() || i < cs1.length()) {
return i;
}
return INDEX_NOT_FOUND;
}
公共静态字符串差异(字符串str1、字符串str2){
如果(str1==null){
返回str2;
}
如果(str2==null){
返回str1;
}
int at=指数差(str1,str2);
if(at==未找到索引){
返回空;
}
返回str2.子字符串(at);
}
公共静态int indexOfDifference(CharSequence cs1、CharSequence cs2){
如果(cs1==cs2){
未找到返回索引;
}
如果(cs1==null | | cs2==null){
返回0;
}
int i;
对于(i=0;i
要查找两行中不同的单词,可以使用以下代码
String[] strList1 = str1.split(" ");
String[] strList2 = str2.split(" ");
List<String> list1 = Arrays.asList(strList1);
List<String> list2 = Arrays.asList(strList2);
// Prepare a union
List<String> union = new ArrayList<>(list1);
union.addAll(list2);
// Prepare an intersection
List<String> intersection = new ArrayList<>(list1);
intersection.retainAll(list2);
// Subtract the intersection from the union
union.removeAll(intersection);
for (String s : union) {
System.out.println(s);
}
String[]strList1=str1.split(“”);
字符串[]strList2=str2.split(“”);
list1=Arrays.asList(strList1);
list2=Arrays.asList(strList2);
//组建工会
列表联合=新的ArrayList(列表1);
union.addAll(列表2);
//准备一个十字路口
列表交点=新的ArrayList(列表1);
交叉口。保留(列表2);
//从并集中减去交点
联轴节。拆除所有(交叉);
for(字符串s:并集){
系统输出打印项次;
}
最后,您将有一个在两个列表中都不同的单词列表。人们可以很容易地修改它,只需将不同的单词放在第一个列表或第二个列表中,而不是同时出现。这可以通过仅从列表1或列表2而不是从并集中删除交点来实现
计算精确位置可以通过将拆分列表中每个单词的长度相加(连同拆分正则表达式)或简单地执行String.indexOf(“subStr”)。要找到两个字符串之间的差异,可以使用StringUtils类和difference方法。它比较两个字符串,并返回它们不同的部分
StringUtils.difference(null, null) = null
StringUtils.difference("", "") = ""
StringUtils.difference("", "abc") = "abc"
StringUtils.difference("abc", "") = ""
StringUtils.difference("abc", "abc") = ""
StringUtils.difference("ab", "abxyz") = "xyz"
StringUtils.difference("abcde", "abxyz") = "xyz"
StringUtils.difference("abcde", "xyz") = "xyz"
请参阅:以下Java代码段有效地计算了必须从相应字符串中删除(或添加)的最小字符集,以使字符串相等。这是动态规划的一个例子
import java.util.HashMap;
import java.util.Map;
public class StringUtils {
/**
* Examples
*/
public static void main(String[] args) {
System.out.println(diff("this is a example", "this is a examp")); // prints (le,)
System.out.println(diff("Honda", "Hyundai")); // prints (o,yui)
System.out.println(diff("Toyota", "Coyote")); // prints (Ta,Ce)
System.out.println(diff("Flomax", "Volmax")); // prints (Fo,Vo)
}
/**
* Returns a minimal set of characters that have to be removed from (or added to) the respective
* strings to make the strings equal.
*/
public static Pair<String> diff(String a, String b) {
return diffHelper(a, b, new HashMap<>());
}
/**
* Recursively compute a minimal set of characters while remembering already computed substrings.
* Runs in O(n^2).
*/
private static Pair<String> diffHelper(String a, String b, Map<Long, Pair<String>> lookup) {
long key = ((long) a.length()) << 32 | b.length();
if (!lookup.containsKey(key)) {
Pair<String> value;
if (a.isEmpty() || b.isEmpty()) {
value = new Pair<>(a, b);
} else if (a.charAt(0) == b.charAt(0)) {
value = diffHelper(a.substring(1), b.substring(1), lookup);
} else {
Pair<String> aa = diffHelper(a.substring(1), b, lookup);
Pair<String> bb = diffHelper(a, b.substring(1), lookup);
if (aa.first.length() + aa.second.length() < bb.first.length() + bb.second.length()) {
value = new Pair<>(a.charAt(0) + aa.first, aa.second);
} else {
value = new Pair<>(bb.first, b.charAt(0) + bb.second);
}
}
lookup.put(key, value);
}
return lookup.get(key);
}
public static class Pair<T> {
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public final T first, second;
public String toString() {
return "(" + first + "," + second + ")";
}
}
}
import java.util.HashMap;
导入java.util.Map;
公共类StringUtils{
/**
*例子
*/
公共静态void main(字符串[]args){
System.out.println(diff(“这是一个示例”,“这是一个examp”);//prints(le,)
System.out.println(diff(“本田”、“现代”);//prints(o,yui)
System.out.println(diff(“丰田”、“郊狼”);//prints(Ta、Ce)
System.out.println(diff(“Flomax”,“Volmax”);//prints(Fo,Vo)
}
/**
*返回必须从相应字段中删除(或添加)的最小字符集
*使字符串相等的字符串。
*/
公共静态对差异(字符串a、字符串b){
返回diffHelper(a,b,newhashmap());
}
/**
*递归地计算最小字符集,同时记住已计算的子字符串。
*在O(n^2)中运行。
*/
私有静态对diffHelper(字符串a、字符串b、映射查找){
long key=((long)a.length())要直接获取更改的部分,而不仅仅是结尾,可以使用Google的
List diff=new DiffMatchPatch().diffMain(“stringend”、“stringdiffend”);
for(Diff-Diff:Diff){
if(diff.operation==operation.INSERT){
return diff.text;//仅返回单个差异,也可以根据用例查找多个差异
}
}
对于Android,添加:implementation'org.bitbucket.cowwoc:diff-match-patch:1.2'
这个软件包比这个功能强大得多,它主要用于创建与diff相关的工具。另一个发现字符串之间差异的伟大库是DiffUtils at。我使用了Dmitry Naumenko的fork:
public void testDiffChange() {
final List<String> changeTestFrom = Arrays.asList("aaa", "bbb", "ccc");
final List<String> changeTestTo = Arrays.asList("aaa", "zzz", "ccc");
System.out.println("changeTestFrom=" + changeTestFrom);
System.out.println("changeTestTo=" + changeTestTo);
final Patch<String> patch0 = DiffUtils.diff(changeTestFrom, changeTestTo);
System.out.println("patch=" + Arrays.toString(patch0.getDeltas().toArray()));
String original = "abcdefghijk";
String badCopy = "abmdefghink";
List<Character> originalList = original
.chars() // Convert to an IntStream
.mapToObj(i -> (char) i) // Convert int to char, which gets boxed to Character
.collect(Collectors.toList()); // Collect in a List<Character>
List<Character> badCopyList = badCopy.chars().mapToObj(i -> (char) i).collect(Collectors.toList());
System.out.println("original=" + original);
System.out.println("badCopy=" + badCopy);
final Patch<Character> patch = DiffUtils.diff(originalList, badCopyList);
System.out.println("patch=" + Arrays.toString(patch.getDeltas().toArray()));
}
Google的Diff Match补丁很好,但是安装到我的Java maven项目中很痛苦。仅仅添加maven依赖项不起作用;eclipse只是创建了目录并添加了最新更新的信息文件。最后,在第三次尝试中,我在pom中添加了以下内容:
<dependency>
<groupId>fun.mike</groupId>
<artifactId>diff-match-patch</artifactId>
<version>0.0.2</version>
</dependency>
显然,这并不是最初编写(甚至没有完全移植)到Java中的
尽管如此,它仍然有效。对于处理长而复杂字符串的人来说,它可能是一个很有价值的工具。据我所知,它不会返回不同的字符,而只是返回字符串不再匹配的整个字符串…@brimborium所以也许你应该澄清你的问题。我认为这个答案非常合适,不是吗原来的问题是:“阿尔科尔,我不是OP;”我不同意。原来的标题有点误导,但问题本身总是清楚地表明他想提取奇数个字符…如果差异不在字符串之后,在中间?如果你需要找到中间字符串差异,请参见JRL的答案。根据对问题的不同解释,最终得到了一个更简单的答案。那么“这是一个测试”和“这是一个测试”是相等的吗?是的。但是op似乎只对charecter的差异感兴趣,而不是
public void testDiffChange() {
final List<String> changeTestFrom = Arrays.asList("aaa", "bbb", "ccc");
final List<String> changeTestTo = Arrays.asList("aaa", "zzz", "ccc");
System.out.println("changeTestFrom=" + changeTestFrom);
System.out.println("changeTestTo=" + changeTestTo);
final Patch<String> patch0 = DiffUtils.diff(changeTestFrom, changeTestTo);
System.out.println("patch=" + Arrays.toString(patch0.getDeltas().toArray()));
String original = "abcdefghijk";
String badCopy = "abmdefghink";
List<Character> originalList = original
.chars() // Convert to an IntStream
.mapToObj(i -> (char) i) // Convert int to char, which gets boxed to Character
.collect(Collectors.toList()); // Collect in a List<Character>
List<Character> badCopyList = badCopy.chars().mapToObj(i -> (char) i).collect(Collectors.toList());
System.out.println("original=" + original);
System.out.println("badCopy=" + badCopy);
final Patch<Character> patch = DiffUtils.diff(originalList, badCopyList);
System.out.println("patch=" + Arrays.toString(patch.getDeltas().toArray()));
}
changeTestFrom=[aaa, bbb, ccc]
changeTestTo=[aaa, zzz, ccc]
patch=[[ChangeDelta, position: 1, lines: [bbb] to [zzz]]]
original=abcdefghijk
badCopy=abmdefghink
patch=[[ChangeDelta, position: 2, lines: [c] to [m]], [ChangeDelta, position: 9, lines: [j] to [n]]]
<dependency>
<groupId>fun.mike</groupId>
<artifactId>diff-match-patch</artifactId>
<version>0.0.2</version>
</dependency>
import fun.mike.dmp.Diff;
import fun.mike.dmp.DiffMatchPatch;
DiffMatchPatch dmp = new DiffMatchPatch();
LinkedList<Diff> diffs = dmp.diff_main("Hello World.", "Goodbye World.");
System.out.println(diffs);
[Diff(DELETE,"Hell"), Diff(INSERT,"G"), Diff(EQUAL,"o"), Diff(INSERT,"odbye"), Diff(EQUAL," World.")]