【问题标题】:Multiple string replacements without affecting substituted text in subsequent iterations多个字符串替换而不影响后续迭代中的替换文本
【发布时间】:2017-02-19 04:08:39
【问题描述】:

我之前已经发布了关于信件的内容,但这是另一个主题,我有一个包含 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 转换为bhduheieja,我不想这样做。

我想根据 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

【问题讨论】:

  • 转化是否遵循特定模式?还是都是任意的?
  • 例如,一种解决方案是使用某种标记来替换{replacement},并考虑{} 逐步替换,最后去掉分隔符{}
  • 我认为@RC。是说,是这样的stackoverflow.com/questions/959731/…
  • 我在我的个人资料中发布了一个关于正则表达式的问题,我正在考虑在更改后的字母之前和之后添加' ',并且在转换字符串时,我会检查它是否在里面' 与否,如果是则不要转换它,如果否则转换它,但是这个想法不起作用,因为它制作起来非常复杂,它适用于低计数字母,但是在写整个单词时,它失败了。
  • @cricket_007 谢谢我在找一个例子;)这个想法是插入分隔符以避免替换替换

标签: java


【解决方案1】:

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

假设是:ab b test a b &gt;&gt;&gt;&gt; bhduheieja eieja neesjt bhduh eieja

那么看下面,Javadoc中的重点是“This will not repeat”

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

【讨论】:

    【解决方案2】:

    尝试以下操作:

    解决方案 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);
    

    【讨论】:

    • 您的解决方案 1 是最可靠的。我讨厌看到每个人因为懒惰而跳到 RegEx。这不是 RegEx 的一个很好的例子,如果你还没有使用它,不是一个很好的(足够的)理由引入 Apache Commons。这是trie 的完美用例。
    【解决方案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

    【讨论】:

      【解决方案4】:

      这是一个严格意义上的 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 列表中的模式并为字符串的其余部分重复算法
      • 否则将字符串的其余部分附加到新字符串中

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          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"
          

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              【解决方案8】:

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

              【讨论】:

              • 示例?因为我没有真正理解你的意思。
              猜你喜欢
              • 1970-01-01
              • 2017-03-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-05-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多