Multiple line replacements without affecting replaced text in subsequent iterations

I wrote about letters before, but this is another topic, I have a json answer that contains 2 objects, from and to , from is what needs to be changed, and to is what it will be changed to.

My code is:

 // 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(); 

For example, json answer:

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

String.replace() will not work here, because first it will replace a with bhduh , then b with eieja , BUT here is the problem, it will convert b to bhduh to eieja , which I don't want.

I want to perfectly convert letters and words to string according to Json, but this is what I fail.

New code:

 if(m_jArry.length() > 0){ HashMap<String, String> m_li; EnteredString = EnteredText.getText().toString(); Log.i("TestAf_","Before Converting: " + EnteredString); HashMap<String,String> replacements = new HashMap<String,String>(); 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(); 

Exit:

 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 
+8
java
source share
8 answers

Here is a method that strictly follows Java. I tried not to use any Java 8 methods.

 public static String translate(final String str, List<String> from, List<String> 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<String> from, List<String> to) { if (null == str) { return null; } return translate(str, from, to, 0); } 

Sample Test Program

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

Output:

 bhduhbhduh hjkyu eiejabhduhneesjh bhduh 

Explaination

The algorithm is recursive and it just does the following

  • If the pattern found in the string matches the pattern in the from list
    • if there is a line before this template, apply the algorithm to this line
    • replace the found pattern with the corresponding pattern in the to list
    • add replacement in a new line
    • drop the pattern in the from list and repeat the algorithm for the rest of the line
  • Otherwise, add the remaining line to a new line
+2
source share

The question will be clearer if you give the expected result for the function.

Assuming this: ab b test ab >>>> bhduheieja eieja neesjt bhduh eieja

then see the following: a key point in Javadoc: β€œThis will not happen again”

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 [])

Replaces all occurrences of strings in another String. The null reference passed to this method is no-op, or if any "search" string "or" string for replacement "is null, this replacement will be ignored. This will not be repeated. To repeat notes, call the overloaded Method.

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

Example 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); } } 
+4
source share

Try the following:

Solution 1: Move the String characters one by one and move the new String to a new StringBuffer or StringBuilder , then call toString() to get the result. This will require you to implement a string matching algorithm.

Solution 2 (using regex): To do this, you need to know the domain of your string. For example, this is [a-zA-Z] , then other arbitrary characters (not part of the domain) can be used for the intermediate step. Replace the actual characters with arbitrary characters first, and then with the target characters arbitrary . In the example below, [!@#] Are arbitrary characters. This can be any random value \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); 
+3
source share

Your problem is pretty common. To summarize:

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

Gives: this is bar test string with bar

Expected by you: this is foo test string with bar

You can use StrSubstitutor from Apache Commons Lang

But first, you have to enter placeholders in the line:

 String test = "this is a test string with foo"; Map<String, String> 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+"}"); } 

And then use the StrSubstitutor

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

It gives: this is foo test string with bar

+3
source share

You can use split as: String[] pieces = jsonResponse.split("},{"); then you simply parse from and in each part and apply them with replacement (), and then concatenate the string again. (and please, do your capitalization of your variables / methods correctly - it’s very difficult to read how you know it)

+1
source share

Apache Commons StringUtils::replaceEach does this.

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

Why not save it very simply (if JSON is always in the same format, EG: from the same system). Instead of replacing from with to , replace all the markup:

replace "from":"*from*" with "from":"*to*"

+1
source share

Why not just change the actual labels to and from? Thus, you are not faced with a situation where "bhudh" becomes "eieja". Just replace the string with "from" and "to."

-3
source share

All Articles