【问题标题】:Tracking brackets in a string跟踪字符串中的括号
【发布时间】:2014-06-23 09:17:41
【问题描述】:

我有以下字符串,并想在我的字符串中跟踪 ROUND( ) 的右括号。

"=ROUND(IF(AND($BY18=2);CA18*CB18/$M$11;IF($BY18=3;CA18*CB18/$M$10;IF($BY18=4;ROUND(CA18*CB18;$M$10)/$M$9;CA18*CB18)))/$M$12;$M$11)";

public class RoundParser {

    public static String parseRound(String text) {

        text = text.toUpperCase();

        String result;

        char[] ch = text.toCharArray();
        int count = -1;
        String temp = "";
        for (int i = 0; i < ch.length; i++) {
            temp = temp + ch[i];

            System.out.println(count);

            if ("ROUND(".equals(temp)) {
                count++;
            }
            if ("(".equals(temp)) {
                count++;
            }
            if (")".equals(temp) && count > 0) {
                count--;
            }
            if (")".equals(temp) && count == 0) {
                ch[i] = '#';
            }
            if (!"ROUND(".startsWith(temp) || temp.length() > 5) {
                temp = "";
            }
        }

        text = String.valueOf(ch);

        result = text;
        return result;
    }

    public static void main(String[] args) {
        String text = "=ROUND(IF(AND($BY18=2);CA18*CB18/$M$11;IF($BY18=3;CA18*CB18/$M$10;IF($BY18=4;ROUND(CA18*CB18;$M$10)/$M$9;CA18*CB18)))/$M$12;$M$11)";

        System.out.println(parseRound(text));
    }

}

但是,目前我正在使用我的解析器:

=ROUND(IF(AND($BY18=2);CA18*CB18/$M$11;IF($BY18=3;CA18*CB18/$M$10;IF($BY18=4;ROUND(CA18*CB18;$M$10)/$M$9;CA18*CB18))#/$M$12;$M$11#

我想要得到的输出是:

=ROUND(IF(AND($BY18=2);CA18*CB18/$M$11;IF($BY18=3;CA18*CB18/$M$10;IF($BY18=4;ROUND(CA18*CB18;$M$10#/$M$9;CA18*CB18)))/$M$12;$M$11#

如您所见,不正确的 ) 被替换为 ;$M$11)";;$M$10)。如果您知道如何替换这两种情况,我将不胜感激。

【问题讨论】:

  • 如果反向开始,遇到的第一个“)”将是最后一个“)”
  • 你必须实现一个for循环并且只检查')'并同时存储它的位置,这样你就可以得到最后一个')'的位置。
  • @TheLostMind 感谢您的回答!请举个例子!
  • 更具体地说明您想要做什么...跟踪最后一个 ')' 或跟踪 ROUND 的右括号?
  • @Kare - 坦率地说..我没有完全得到你的问题..你想做什么?给出示例输入和输出..

标签: java string algorithm


【解决方案1】:

有两种方法

1) 如果左括号和右括号的数量总是相等,那么您可以使用 for 循环跟踪最后一个右括号。

2)如果你不确定左右括号是否相等,那么你可以这样做-->

public class RoundParser {

    public static String parseRound(String text) {

        text = text.toUpperCase();

        String result;

        char[] ch = text.toCharArray();

     int count=0,pos=0;
        int c[10];
        for(int i=0;i<ch.length;i++){

        if(ch[i].equals("(")){
        count++;  
         if(ch[i-1].equals("D")){
              c[pos]=count;   //will store the count value at every opening round
                  pos++;
              }
        }

        if(ch[i].equals(")")){
        count--;
         for(int j=0;j<10;j++){
             if(c[j]==count)   //if the closing of round had been encountered
                   ch[i]="#";   
         }
       }

        }


        text = String.valueOf(ch);

        result = text;
        return result;
    }

    public static void main(String[] args) {
        String text = "=ROUND(IF(AND($BY18=2);CA18*CB18/$M$11;IF($BY18=3;CA18*CB18/$M$10;IF($BY18=4;ROUND(CA18*CB18;$M$10)/$M$9;CA18*CB18)))/$M$12;$M$11)";

        System.out.println(parseRound(text));
    }

}

你去。

我认为这应该可行。

希望这会有所帮助。

【讨论】:

  • +1.ya.. 这应该可以工作(如果我正确理解了 OP 的问题..)
  • @aradhna 请把它放到一个工作函数中,我会接受你的回答!
  • @Kare 你想让我做什么?
  • @aradhna 如果你能把它放到一个工作函数中,我将不胜感激,这样我就可以接受你的回答!
【解决方案2】:

你忘记了else

else if (")".equals(temp) && count == 0) {

这将减少count,如果然后count==0,它将减少两次。

【讨论】:

    【解决方案3】:

    这个问题可以递归解决。

    首先,您使用方法.indexOf("ROUND(") 来检测第一次出现的round()。

    然后,我们需要确定哪一个是本轮() 的结尾')'。一个简单的算法就足够了:

    int start = text.indexOf("ROUND(") + "ROUND(".length();
    
    int count = 1;
    int end = -1;
    for(int i = start; i < text.length; i++){ 
        if(text.charAt(i) == '('){
           count++;
        }else if(text.charAt(i) == ')'){
           count--;
        }
        if(count == 0){
           end = i;
           break;
        }
    } 
    

    检测到外层round()的开始和结束后,可以使用text.substring(start, end)去掉外层round(),递归继续上述函数,直到找到所有round()

    【讨论】:

      【解决方案4】:

      为了识别多个ROUND(X),我建议

      TreeMap<Integer,Pair<Integer,Integer>> map = new TreeMap<>();
      
      int count = 0;
      

      我们在哪里存储&lt;start_index, &lt;init_count, end_index&gt;&gt;

      if ("ROUND(".equals(temp))
      {
          map.put(i, new Pair<Integer,Integer>(count, -1));
          count++;
      }
      
      if ("(".equals(temp)) count++;
      
      if (")".equals(temp))
      {
          if (count <= 0)
          {
              count = 0;
              // Error: extra closing bracket
          }
          else
          {
              count--;
          }
      
          int max_i = -1;
      
          for (Integer index : map.keySet())
          {
              if (index > max_i
                && map.get(index).second() == -1
                && map.get(index).first() == count)
              {
                  max_i = index;
              }
          }
      
          if (max_i > -1) map.get(max_i).setSecond(i);
      }
      

      【讨论】:

      • 感谢您的回答!但是,如果不将其放入方法中,我很难尝试一下。非常感谢您的回答!
      • @Kare这是一个伪代码,你需要整合这个想法,我的想法是使用start indexes的映射并寻找与init count匹配的closing bracket call .. 另请注意,您需要编写一个类Pair
      【解决方案5】:

      这是一个算法.. 如果您不确定最后一个“)”是否是您正在寻找的那个。 从字符串的索引 0 开始,对于您遇到的每个“(”,增加计数,对于每个“)”减少计数,将“)”替换为“#”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-01
        • 1970-01-01
        • 2016-06-27
        • 1970-01-01
        • 2019-07-17
        • 1970-01-01
        • 2015-03-21
        相关资源
        最近更新 更多