3

我有一个字符串输入,它代表一个公式,例如:

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

我希望能够将所有合法变量提取到String[]

合法变量的确定规则与 Java 变量命名约定几乎相同,但只允许使用字母数字字符:

  • 任何大写或小写字母字符都可以后跟一个数字
  • 任何单词/文本
  • 任何单词/文本后跟一个数字

因此,我希望输出如下所示:

BMI
Weight
Height

这是我目前的尝试:

/* 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; 
}

结果并不如我所料。我得到了额外的空行,两次得到“高度”,不应该得到一个数字:

BMI


Weight


Height


Height



703
4

3 回答 3

4

我不确定您为什么要创建一个字符串并将其拆分以转换为数组。除了效率低下之外,除非每个 ID 出现后面都有空格,否则该方法将不起作用。

这是一个更简单的代码,允许在输出中重复。要摆脱重复,只需将ListandArrayList替换为Setand 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);
        }
    }
}

如果您实际上想要 aString []作为返回值而不是ArrayList<String>,则在返回时进行转换。

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

最后,我想知道您要完成什么。在表达式中包含标识符列表似乎不是很有用。例如,如果您尝试评估表达式,则此 id 列表将不是您所需要的。

于 2012-06-26T02:13:00.833 回答
0

使用:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Main
{
  public static void main (String[] args) throws java.lang.Exception
  {
     String formula = "BMI = ( Weight / ( Height * Height ) ) * 703";
     String pattern = "(?:^|(?<=[=+\\-*/()]))\\s*([a-z]+)\\s*(?:$|(?=[=+\\-*/()]))";
     Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
     Matcher m = p.matcher(formula);
     while(m.find()) {
       System.out.println(m.group(1));
     }
  }
}

你会得到:

BMI
Weight
Height
Height

因此,之后您需要做的就是删除重复项,这是一项简单的任务。


在此处查看并测试代码。

于 2012-06-26T00:22:03.170 回答
0

这个简单的正则表达式应该为您匹配所有变量:

"[A-Za-z_][A-Za-z0-9_]*"

我冒昧地将其包含_在名称中,但如果您真的不想要,可以将其删除:

"[A-Za-z][A-Za-z0-9]*"

不可能唯一地匹配变量,但您可以插入匹配Set项以删除重复的条目。

于 2012-06-26T00:56:34.913 回答