从字符串中提取公式

时间:2015-01-29 06:50:38

标签: c# .net

我必须从公式

中提取所有变量

Fiddle for below problem

  

例如。 (FB + AB + ESI)/ 12

     

输出{FB,AB,ESI}

到目前为止编写的代码

var length = formula.Length;
            List<string> variables = new List<string>();
            List<char> operators = new List<char> { '+', '-', '*', '/', ')', '(', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
            int count = 0;
            string character = string.Empty;
            for (int i = 0; i < length; i++)
            {
                if (!operators.Contains(formula[i]))
                    character += formula[i];
                else
                {
                    if (!string.IsNullOrWhiteSpace(character))
                        variables.Add(character);
                    character = string.Empty;
                    count = i;
                }
            }
            if (!string.IsNullOrWhiteSpace(character))
                variables.Add(character);
            return variables;
  

方法的输出是{FB,AB,ESI},这是正确的

我的问题是Varaible包含数字字段,即

  

例如。 (FB1 + AB1)/ 100

     

预期输出:{FB1,AB1}

     

但我的方法返回{FB,AB}

6 个答案:

答案 0 :(得分:2)

如果变量的名称​​必须以

开始
   letter A..Z, a..z

如果变量的名称​​可以包含

  letters     A..Z, a..z
  digits      0..1
  underscopes _

你可以使用正则表达式:

  String source = "(FB2+a_3B+EsI) / 12";

  String pattern = @"([A-Z]|[a-z])+([A-z]|[a-z]|\d|_)*";

  // output will be "{FB2,a_3B,EsI}"
  String output = "{" + String.Join(",", 
    Regex.Matches(source, pattern)
      .OfType<Match>()
      .Select(item => item.Value)) + "}";

如果您需要集合,请说一个变量名称数组,只需修改Linq:

  String names[] = Regex.Matches(source, pattern)
    .OfType<Match>()
    .Select(item => item.Value)
    .ToArray();

然而,实现的只是一种天真的标记器:你必须分离变量名称&#34;从函数名,类名中找到,检查它们是否被注释掉等。

答案 1 :(得分:2)

已经更改了您的代码以执行您的要求,但不确定解决方案的方法,并且未考虑括号和运算符优先级。

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        string formula = "AB1+FB+100";
        var length = formula.Length;
        List<string> variables = new List<string>();
        List<char> operators = new List<char>{'+', '-', '*', '/', ')', '('};
        List<char> numerals = new List<char>{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

        int count = 0;
        string character = string.Empty;
        char prev_char = '\0';

        for (int i = 0; i < length; i++)
        {
            bool is_operator = operators.Contains(formula[i]);
            bool is_numeral = numerals.Contains(formula[i]);
            bool is_variable = !(is_operator || is_numeral);
            bool was_variable = character.Contains(prev_char);

            if (is_variable || (was_variable && is_numeral) )
                character += formula[i];
            else
            {
                if (!string.IsNullOrWhiteSpace(character))
                    variables.Add(character);
                character = string.Empty;
                count = i;
            }

            prev_char = formula[i];
        }

        if (!string.IsNullOrWhiteSpace(character))
            variables.Add(character);

        foreach (var item in variables)
            Console.WriteLine(item);
        Console.WriteLine();
        Console.WriteLine();
    }
}

也许还会考虑类似Math-Expression-Evaluator (on nuget)

的内容

答案 2 :(得分:1)

以下是使用正则表达式执行此操作的方法。

        Regex regex = new Regex(@"([A-Z])\w+");

        List<string> matchedStrings = new List<string>();
        foreach (Match match in regex.Matches("(FB1+AB1)/100"))
        {
            matchedStrings.Add(match.Value);
        }

这将创建所有匹配的字符串列表。

答案 3 :(得分:1)

如果没有正则表达式,您可以拆分实际的运算符(而不是数字),然后删除任何以数字开头的项目:

public static List<string> GetVariables(string formula)
{
    if (string.IsNullOrWhitespace(formula)) return new List<string>();

    var operators = new List<char> { '+', '-', '*', '/', '^', '%', '(', ')' };

    int temp;
    return formula
        .Split(operators.ToArray(), StringSplitOptions.RemoveEmptyEntries)
        .Where(operand => !int.TryParse(operand[0].ToString(), out temp))
        .ToList();
}

答案 4 :(得分:0)

您可以这样做,只需根据需要优化代码。

       string ss = "(FB+AB+ESI) / 12";

        string[] spl =  ss.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
        string final = spl[0].Replace("(", "").Replace(")", "").Trim();
        string[] entries = final.Split(new char[] {'+'}, StringSplitOptions.RemoveEmptyEntries);
        StringBuilder sbFinal = new StringBuilder();
        sbFinal.Append("{");
        foreach(string en in entries)
        {
            sbFinal.Append(en + ",");
        }
        string finalString = sbFinal.ToString().TrimEnd(',');
        finalString += "}";

答案 5 :(得分:0)

你要做的是翻译。

我不能给你整个代码,但我能给你的是一个先发优势(它需要大量的编码)。

首先,了解reverse polish notation

其次,您需要了解stacks

第三,你必须同时申请两者来获得你想要解释的内容。