Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java regex , matching variables in a math expression [closed]

Tags:

java

regex

I have a string input that represents a formula like:

BMI = ( Weight / ( Height  * Height ) ) * 703

I want to be able to extract all legal variables into a String[]

Legal variables are determined with almost the same rules as Java variable naming convention, except only alphanumeric characters are allowed:

  • Any alphabet character upper or lower, may be followed by a digit
  • Any word/text
  • Any word/text followed by a digit

Therefore I expect the output to look like this:

BMI
Weight
Height

This is my current attempt:

/* helper method , find all variables in expression,
 * Variables are defined a alphabetical characters a to z, or any word , variables cannot have numbers at the beginning
 * using regex pattern "[A-Za-z0-9\\s]"
 */
public static List<String> variablesArray (String expression)
{
    List<String> varList = null; 
    StringBuilder sb = null; 
    if (expression!=null)
    {
        sb = new StringBuilder(); 

        //list that will contain encountered words,numbers, and white space
        varList = new ArrayList<String>();

        Pattern p = Pattern.compile("[A-Za-z0-9\\s]");
        Matcher m = p.matcher(expression);

        //while matches are found 
        while (m.find())
        {
            //add words/variables found in the expression 
            sb.append(m.group());
        }//end while 

        //split the expression based on white space 
        String [] splitExpression = sb.toString().split("\\s");
        for (int i=0; i<splitExpression.length; i++)
        {
            varList.add(splitExpression[i]);
        }
    }
    return varList; 
}

The result is not as I expected. I got extra empty lines, got "Height" twice, and shouldn't have gotten a number:

BMI


Weight


Height


Height



703
like image 372
cyber101 Avatar asked Sep 22 '26 11:09

cyber101


1 Answers

I'm not sure why you would make a string and split it to convert to an array. In addition to its inefficiency, the method won't work unless every ID occurrence is followed by space.

Here's a more straightforward code that allows repeats in the output. To get rid of repeats, just replace List and ArrayList with Set and HashSet:

public class Test {

    public static List<String> variablesArray(String expression) {
        if (expression != null) {
            ArrayList<String> vars = new ArrayList<String>();
            Pattern p = Pattern.compile("[a-z][a-z0-9]*", Pattern.CASE_INSENSITIVE);
            Matcher m = p.matcher(expression);
            while (m.find()) {
                vars.add(m.group());
            }
            return vars;
        }
        return null;
    }

    public static void main(String[] args) {
        List<String> vars = variablesArray("BMI=(Weight/(Height*Height)) * 70");
        for (String var : vars) {
            System.out.println(var);
        }
    }
}

If you actually want a String [] as the return value rather than the ArrayList<String>, then do the conversion as you're returning.

return vars.toArray(new String [vars.size()]);

Finally, I wonder what you are trying to accomplish. Having a list of identifiers in an expression doesn't seem very useful. If, for example, you are trying to evaluate the expression, this list of ids is not going to be what you need.

like image 196
Gene Avatar answered Sep 25 '26 01:09

Gene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!