问题
I'm working on a piece of code where I've to split a string into individual parts and replace them. The basic logic flow of my code is, there's a string that contains a formula. The numbers below on the LHS, i.e 1, 2 and 3 are ids of different objects. Once I split them, I'd use these ids, get the respective value and replace the ids in the below String with its respective values. The string that I have is as follow -
String str = "(1+2+3)>100";
I've used the following code for splitting the string -
String[] arraySplit = str.split("\\>|\\<|\\=");
String[] finalArray = arraySplit[0].split("\\(|\\)|\\+|\\-|\\*");
arraySplit[0] = arraySplit[0].replace(id,reading);
So, after the string is split, I'd replace the string with the values, i.e the string would now be, (30+45+50)>100
where 30, 45 and 50 are the respective values. (this string would then be used in SpEL to evaluate the formula)
While replacing the string with the values, I'm getting the following response -
Initial string -
(1+2+3)>100
where 1, 2 and 3 are ids. Respective values of the ids are 30.0, 45.0 and 50.0.
After replacing the value by using a for loop, the string is -
(50.00.0+45.0+50.0)>100
. The first value is quite weird. The reason for this is while in the third iteration, the string looked like this - (30.0+45.0+3)>100. So while replacing the string in the third iteration, it replaces all instances of 3 with 50.0 hence resulting in the above string. So apparently using String.replace()
won't be a better option here. What method should I use in this case then? I'm also using SpEL, so if there's a better solution to this using SpEL then also its good.
Here, (1+2+3)>100
is just an example. The round braces are part of a formula, and the string could also be as ((1+2+3)*(5-2))>100
. Or even the syntax of the formula could be changed, currently the formula is as such - (1+2+3) * 4>100 but if there's a way out by changing the formula syntax a bit then that would also be helpful, e.g replacing the formula by - ({#1}+{#2}+{#3}) *
{#4}>100, in this case I'd get the variable using {# as the variable and get the numbers.
I hope this part is clear.
回答1:
You're right, String.replace
is not the right tool for the job here.
What you want to do is to tokenize the input string, then operate on the tokens. Optionally you can combine back into a string at the end, but it depends on what you intend to do with the formula.
For example, you want to tokenize the string "(1+2+3)>100"
into the array ["(", "1", "+", "2", "+", "3", ")", ">", "100"]
. This is simply a matter of splitting on every boundary between a digit and a symbol.
From this representation, it's a simple matter to replace the entire tokens in the array with their corresponding values, e.g. find the array index that has value "1"
and replace it with "30.0"
, etc. Then you can create a new expression string by just joining all the parts in the array back together.
If you want to go one step further, you can translate into an expression tree, which would look something like this:
OpGreaterThan
OpPlus
Symbol(1)
OpPlus
Symbol(2)
Symbol(3)
Literal(100)
This tree is formed by transforming the input expression (which is rendered in standard infix notation) into reverse polish notation, then building a tree where each node is an operator and its children are operands. This would allow you to symbolically manipulate and/or evaluate the formula.
来源:https://stackoverflow.com/questions/43720022/string-replace-returns-unwanted-string