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

时间:2016-10-10 17:05:44

标签: java

我之前发过关于字母的信,但这是另一个话题,我有一个包含2个对象的json响应,fromtofrom是要改变的,而to就是它将被改变的地方。

我的代码是:

// for example, the EnteredText is "ab b test a b" .
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()方法在这里不起作用,因为首先它会将a替换为bhduh,然后b替换为eieja,但这是问题,它会将b中的bhduh转换为eieja,这是我不想要的。

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

新守则:

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

输出:

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 个答案:

答案 0 :(得分:4)

如果您为函数提供了预期的输出,那么您的问题会更清楚。

假设它是:ab b test a b >>>> 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中出现的所有字符串。   传递给此方法的空引用是无操作或任何“搜索”   string“或”要替换的字符串“为null,将忽略该替换。    这不会重复。 要重复替换,请调用重载   方法

示例1

import org.apache.commons.lang3.StringUtils;

public class StringReplacer {

    public static void main(String[] args) {

        String input = "ab b test a b";
        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 :(得分:3)

请尝试以下操作:

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

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

String input = "a-b-c";
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);

答案 2 :(得分:3)

你的问题非常普遍。总结一下:

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

然后,使用StrSubstitutor

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

它给出:this is foo test string with bar

答案 3 :(得分:2)

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

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

样本测试程序

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

输出:

bhduhbhduh  hjkyu  eiejabhduhneesjh  bhduh

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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"

答案 6 :(得分:1)

为什么不保持简单(如果JSON始终采用相同的格式,EG:来自同一系统)。不要将from替换为to,而是替换整个标记:

"from":"*from*"替换为"from":"*to*"

答案 7 :(得分:-3)

为什么不将实际的&#34;更改为&#34; &#34;来自&#34;标签?这样,你就不会遇到这样的情况:&#34; bhudh&#34;成为&#34; eieja&#34;。只需在&#34;&#34;中进行字符串替换和&#34;到&#34;。