用值替换变量名称

时间:2013-08-19 07:39:25

标签: c#

我使用以下值定义一个字符串:

var filterMe = "foo=1;bar=foo+5;foobar=foo+5-bar;";

创建一个像这样分割字符串的数组:

var splitter = filterMe.Split(';');

Dictionary<string,string> dictionary = new Dictionary<string, string>();

foreach (var split in splitter)
        {
            if (!string.IsNullOrEmpty(split))
            {
                var part = split.Split('=');
                dictionary.Add(part[0], part[1]);
            }
        }

因此字典中“bar = foo + 5”的结果定义为“bar”,“foo + 5”。

现在我的问题是,如何将值“foo + 5”中的“foo”更改为包含值“1”的键“foo”? 字符串filterMe将更长且动态,因此它将包含多个变量(foo)。

修改:由于我的问题似乎有点令人困惑,请参阅下面有关如何更换的信息:

var foo=200;
var bar = foo+300;

变量栏应该变为:

var bar = 200+300;

4 个答案:

答案 0 :(得分:0)

这个库似乎可以满足您的需求 http://csharpeval.codeplex.com/wikipage?title=Usage&referringTitle=Home

执行拆分后,按顺序遍历字典中的每个值,并将值(foo)作为临时动态对象的成员(如果您使用.net 4,如果不是字典)

然后使用库来评估第二个表达式,将其结果存储在临时对象/字典中,然后继续。

答案 1 :(得分:0)

您还需要变量的数组或字典及其值(例如Foo,5)。将分号(filterMe.Split(“;”)上的字符串拆分为数组以获取元素,然后循环并拆分“=”上的元素,使用返回数组的数组[0]作为键在字典和数组[1]中作为值。 最后循环遍历变量和值数组,以用正确的值替换键。为了执行计算(例如foo-5),我将创建一个Func<string, string, int>,它接受​​你要在字典中作为字符串执行计算的2个int,删除运算符,将它们解析为int,然后使用字符串运算符决定执行哪个操作(+, - 等...),最后返回计算值的int(或我猜的字符串)

答案 2 :(得分:0)

以下测试通过: (未考虑性能因素

[Test]
public void tst()
{
    var filterMe = "foo=1;bar=foo+5;foobar=foo+5-bar;";
    var dic = filterMe.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
                      .ToDictionary(x => x.Split('=')[0], x => x.Split('=')[1]);

    while (true)
    {
        var kvpToApply = dic.Keys
                            .Join(dic, x => true, y => true, (key, value) => new { key, value })
                            .FirstOrDefault(x => x.value.Value.Contains(x.key));
        if (kvpToApply != null)
        {
            dic[kvpToApply.value.Key] = kvpToApply.value.Value.Replace(kvpToApply.key, dic[kvpToApply.key]);
        }
        else
        {
            break;
        }
    }

    Assert.AreEqual("1", dic["foo"]);
    Assert.AreEqual("1+5", dic["bar"]);
    Assert.AreEqual("1+5-1+5", dic["foobar"]);
}

答案 3 :(得分:0)

这将有效:

public enum ParserState
{
    ExpectSign = 0,
    ExpectValue = 1
}

public static void Parse()
{
    string filterMe = "foo=1;bar=foo+5;foobar=foo+5-bar;";

    var rows = filterMe.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

    Dictionary<string, int> locals = new Dictionary<string, int>();

    foreach (string split in rows)
    {
        var row = split.Split('=');

        if (row.Length != 2)
        {
            throw new Exception();
        }

        string name = row[0].Trim();
        string exp = row[1].Trim();

        if (!Regex.IsMatch(name, "^[A-Za-z_]+$"))
        {
            throw new Exception();
        }

        Regex rx = new Regex(@"\G(?:(?<local>[A-Za-z_]+)|(?<constant>[0-9]+)|(?<sign>[+-]))");

        var subExps = rx.Matches(exp).OfType<Match>().ToArray();

        if (subExps.Length == 0 || subExps[subExps.Length - 1].Index + subExps[subExps.Length - 1].Length != exp.Length)
        {
            throw new Exception();
        }

        int result = 0;

        ParserState state = ParserState.ExpectValue;
        string currentSign = "+";

        foreach (var subExp in subExps)
        {
            {
                Group sign = subExp.Groups["sign"];

                if (sign.Success)
                {
                    if (state != ParserState.ExpectSign)
                    {
                        throw new Exception();
                    }

                    currentSign = sign.ToString();

                    state = ParserState.ExpectValue;

                    continue;
                }
            }

            {
                Group local = subExp.Groups["local"];

                if (local.Success)
                {
                    if (state != ParserState.ExpectValue)
                    {
                        throw new Exception();
                    }

                    int value;

                    if (!locals.TryGetValue(local.ToString(), out value))
                    {
                        throw new Exception();
                    }

                    result = Operation(result, value, currentSign);

                    state = ParserState.ExpectSign;
                }
            }

            {
                Group constant = subExp.Groups["constant"];

                if (constant.Success)
                {
                    if (state != ParserState.ExpectValue)
                    {
                        throw new Exception();
                    }

                    int value = int.Parse(constant.ToString());

                    result = Operation(result, value, currentSign);

                    state = ParserState.ExpectSign;
                }
            }

            if (state != ParserState.ExpectSign)
            {
                throw new Exception();
            }
        }

        locals[name] = result;
    }
}

private static int Operation(int result, int value, string currentSign)
{
    if (currentSign == "+")
    {
        return result + value;
    }

    if (currentSign == "-")
    {
        return result - value;
    }

    throw new ArgumentException();
}

但请注意,如果您想在运算符之间引入()或不同的优先级(以便1 * 2 + 3 == (1 * 2) + 3)或数字符号(1 + -2)或(-2 + 1 )变得非常困难。

有一些工具/库可以完成这类工作。

最后,它会考虑以这种格式制作的“行”:

local = [local|constant]([+|-][local|constant])*