Reputation: 5355
I am having the following string and want to track the closing bracket of ROUND(
)
in my string.
"=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));
}
}
However, using my parser at the moment I am getting:
=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#
The output I want to get is:
=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#
As you can see the not the right ) are replaced, as ;$M$11)";
and ;$M$10)
. I really appreciate if you have any idea how to repalce these two cases.
Upvotes: 1
Views: 186
Reputation: 983
there are 2 approaches to this
1) if the number of opening and closing brackets are always going to be equal, then you can just track the last closing bracket by using a for loop.
2) if you are not sure about opening and closing brackets to be equal, then you can so the following-->
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));
}
}
there you go.
i think this should work.
hope this helps.
Upvotes: 2
Reputation: 5950
For recognition of multiple ROUND(X)
, I suggest
TreeMap<Integer,Pair<Integer,Integer>> map = new TreeMap<>();
int count = 0;
Where we store <start_index, <init_count, end_index>>
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);
}
Upvotes: 1
Reputation: 11294
This problem can be done recursively.
First, you use method .indexOf("ROUND(")
to detect the first occurrence of round().
Then, we need to determine which is the end ')' of this round(). A simple algo will be enough :
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;
}
}
After you detect the start and end of the outer round()
, you can use text.substring(start, end)
to remove the outer round(), and continue the above function recursively, until you find all round()
Upvotes: 2
Reputation: 36304
Here's an algorithm.. If you are not sure that the last ")" would be the one you are looking for. Start from index 0 of the String, for each "(" you encounter, increment the count, and for each ")" decrement the count, replace the ")" with "#".
Upvotes: 0
Reputation: 5101
You forgot an else
:
else if (")".equals(temp) && count == 0) {
That will decrement count
and if then count==0
, it will decrement twice.
Upvotes: 2