多个字符串替换,不会影响后续迭代中的替换文本

我之前发过关于字母的信,但这是另一个主题,我有一个包含2个对象的json响应, fromtofrom是要改变什么,以及它将被改变为什么。

我的代码是:

 // for example, the EnteredText is "ab b test ab" . EnteredString = EnteredText.getText().toString(); for (int i = 0; i < m_jArry.length(); i++) { JSONObject jo_inside = m_jArry.getJSONObject(i); String Original = jo_inside.getString("from"); String To = jo_inside.getString("to"); if(isMethodConvertingIn){ EnteredString = EnteredString.replace(" ","_"); EnteredString = EnteredString.replace(Original,To + " "); } else { EnteredString = EnteredString.replace("_"," "); EnteredString = EnteredString.replace(To + " ", Original); } } LoadingProgress.setVisibility(View.GONE); SetResultText(EnteredString); ShowResultCardView(); 

例如,json响应是:

 { "Response":[ {"from":"a","to":"bhduh"},{"from":"b","to":"eieja"},{"from":"tes","to":"neesj"} ] } 

String.replace()方法在这里不起作用,因为首先它将替换为bhduh ,然后b替换为eieja ,但是这里是问题,它会将bhduh b转换为eieja ,这是我不想要的。

我希望根据Json完美地转换字符串中的字母和“单词”,但那是我失败的原因。

新代码:

 if(m_jArry.length() > 0){ HashMap m_li; EnteredString = EnteredText.getText().toString(); Log.i("TestAf_","Before Converting: " + EnteredString); HashMap replacements = new HashMap(); for (int i = 0; i < m_jArry.length(); i++) { JSONObject jo_inside = m_jArry.getJSONObject(i); String Original = jo_inside.getString("from"); String To = jo_inside.getString("to"); if(isMethodConvertingIn){ //EnteredString = EnteredString.replace(" ","_"); replacements.put(Original,To); Log.i("TestAf_","From: " + Original + " - To: " + To + " - Loop: " + i); //EnteredString = EnteredString.replace(" ","_"); //EnteredString = EnteredString.replace(Original,To + " "); } else { EnteredString = EnteredString.replace("_"," "); EnteredString = EnteredString.replace("'" + To + "'", Original); } } Log.i("TestAf_","After Converting: " + replaceTokens(EnteredString,replacements)); // Replace Logic Here // When Finish, Do : LoadingProgress.setVisibility(View.GONE); SetResultText(replaceTokens(EnteredString,replacements)); ShowResultCardView(); 

输出:

 10-10 19:51:19.757 12113-12113/? I/TestAf_: Before Converting: ab a ba 10-10 19:51:19.757 12113-12113/? I/TestAf_: From: a - To: bhduh - Loop: 0 10-10 19:51:19.757 12113-12113/? I/TestAf_: From: b - To: eieja - Loop: 1 10-10 19:51:19.757 12113-12113/? I/TestAf_: From: o - To: neesj - Loop: 2 10-10 19:51:19.758 12113-12113/? I/TestAf_: After Converting: ab a ba 

这是一种严格来说只是Java的方法。 我试着在这里不使用任何Java 8方法。

 public static String translate(final String str, List from, List to, int index) { StringBuilder components = new StringBuilder(); String token, replace; int p; if (index < from.size()) { token = from.get(index); replace = to.get(index); p = 0; for (int i = str.indexOf(token, p); i != -1; i = str.indexOf(token, p)) { if (i != p) { components.append(translate(str.substring(p, i), from, to, index + 1)); } components.append(replace); p = i + token.length(); } return components.append(translate(str.substring(p), from, to, index + 1)).toString(); } return str; } public static String translate(final String str, List from, List to) { if (null == str) { return null; } return translate(str, from, to, 0); } 

样本测试程序

 public static void main(String []args) { String EnteredString = "aa hjkyu batesh a"; List from = new ArrayList<>(Arrays.asList("a", "b", "tes")); List to = new ArrayList<>(Arrays.asList("bhduh", "eieja", "neesj")); System.out.println(translate(EnteredString, from, to)); } 

输出:

 bhduhbhduh hjkyu eiejabhduhneesjh bhduh 

该算法是递归的,它只是执行以下操作

  • 如果字符串中找到的模式与from列表中的模式匹配
    • 如果在该模式之前有任何字符串,则将算法应用于该字符串
    • 将所找到的模式替换为to列表中的相应模式
    • 将替换附加到新字符串
    • 丢弃from列表中的模式,并为字符串的其余部分重复算法
  • 否则,将其余字符串附加到新字符串

如果你给出函数的预期输出,你的问题会更清楚。

假设它是: ab b test ab >>>> bhduheieja eieja neesjt bhduh eieja

然后看看以下内容,Javadoc中的关键点是“这不会重复”

http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html#replaceEach(java.lang.String中,%20java.lang.String [] ,%20java.lang.String [])

替换另一个String中出现的所有字符串。 传递给此方法的空引用是无操作,或者如果任何“搜索字符串”或“要替换的字符串”为空,则将忽略该替换。 这不会重复。 要重复替换,请调用重载方法。

例1

 import org.apache.commons.lang3.StringUtils; public class StringReplacer { public static void main(String[] args) { String input = "ab b test ab"; String output = StringUtils.replaceEach(input, new String[] { "a", "b", "tes" }, new String[] { "bhduh", "eieja", "neesj" }); System.out.println(input + " >>>> " + output); } } 

例2

 import org.apache.commons.lang3.StringUtils; public class StringReplacer { public static void main(String[] args) { String input = "this is a test string with foo"; String output = StringUtils.replaceEach(input, new String[] { "a", "foo" }, new String[] { "foo", "bar"}); System.out.println(input + " >>>> " + output); } } 

试试以下:

解决方案1:逐个遍历String字符并将新String移动到新的StringBufferStringBuilder ,然后调用toString()以获取结果。 这将需要您实现字符串匹配算法。

解决方案2(使用Regex):为此,您必须知道字符串的域。 例如,它是[a-zA-Z]那么其他任意字符(不是域的一部分)可以用于中间步骤。 首先用任意一个替换实际字符,然后用目标替换任意一个 。 在下面的示例中, [!@#]是任意字符。 这些也可以是任何随机\uxxxx值。

 String input = "abc"; String output = input.replaceAll("[a]", "!").replaceAll("[b]", "@").replaceAll("[c]", "#"); output = output.replaceAll("[!]", "bcd").replaceAll("[@]", "cde").replaceAll("[#]", "def"); System.out.println("input: " + input); System.out.println("Expected: bcd-cde-def"); System.out.println("Actual: " + output); 

你的问题很常见。 总结一下:

 String test = "this is a test string with foo"; System.out.println(test.replace("a", "foo").replace("foo", "bar")); 

给: this is bar test string with bar

您期待: this is foo test string with bar

您可以使用Apache Commons Lang的 StrSubstitutor

但首先,您必须在字符串中注入占位符:

 String test = "this is a test string with foo"; Map valuesMap = new HashMap<>(); valuesMap.put("a", "foo"); valuesMap.put("foo", "bar"); String testWithPlaceholder = test; // Preparing the placeholders for (String value : valuesMap.keySet()) { testWithPlaceholder = testWithPlaceholder.replace(value, "${"+value+"}"); } 

然后,使用StrSubstitutor

 System.out.println(StrSubstitutor.replace(testWithPlaceholder, valuesMap)); 

它给出: this is foo test string with bar

您可以使用split: String[] pieces = jsonResponse.split("},{"); 然后你只需解析每个部分中的from和to并用replace()应用它们然后再将字符串重新组合在一起。 (并且请将您的变量/方法大写正确 – 这使得您很难阅读它的方式)

Apache Commons StringUtils::replaceEach这样做的。

 String[] froms = new String[] {"a", "b"}; String[] tos = new String[] {"b","c"}; String result = StringUtils.replaceEach("ab", froms, tos); // result is "bc" 

为什么不保持它非常简单(如果JSON总是以相同的格式,EG:来自同一系统)。 而不是替换to ,替换整个标记:

"from":"*from*"替换"from":"*from*" with "from":"*to*"

为什么不改变实际的“to”和“from”标签呢? 这样,你就不会遇到“bhudh”成为“eieja”的情况。 只需在“from”和“to”上进行字符串替换。