【问题标题】:Replace string smartly巧妙地替换字符串
【发布时间】:2022-01-11 05:32:26
【问题描述】:

我正在尝试将变量替换为文本字符串中的,这是一个数学表达式。

math_Expresion = d + dft-t 

到它的当前值:

 1 + 32 - 4

然后用DataTable()进行计算

var result = new DataTable().Compute(math_Expresion, null);

但如果一个变量作为名称包含另一个例子,它就不起作用

a = 1
aa = 22
d = a + aa
d.Replace ("a", a)
d.Replace ("aa", aa)
return 1 + 11 not 1 + 22

混淆了名称。 有没有办法用它们的值替换名称而不跳过它们、一些ReplaceExacly() 函数或类似的东西来避免这种不适?

实际代码:

    for (int i = 0; i < variables_cache.Count; i++)
    {
        if (math_expresion.Contains(variables_cache[i].name))
        {
            math_expresion = math_expresion.Replace(variables_cache[i].name, variables_cache[i].value);
        }
    }

    var result = new DataTable().Compute(math_expresion, null);

【问题讨论】:

  • 切换d.Replace ("a", a) & d.Replace ("aa", aa)
  • 这是在for循环中完成的,我无法控制元素的顺序,所以...
  • 听起来你正在重新发明dynamic compilation的轮子
  • @Moix 你是编写代码的人,不是吗?那么除了你还有谁可以控制?您可以按长度降序对值进行排序。

标签: c# string variables replace


【解决方案1】:

您不必对公式做任何事情,您可以将变量传递为DataColumns:

private static object Compute(string formula, 
                              IDictionary<string, object> variables = null) {
  // using - don't forget to Dispose table which is IDisposable
  using (DataTable table = new DataTable()) {
    // If we have variables... 
    if (variables != null)
      foreach (var pair in variables) // ... we create columns 
        table.Columns.Add(pair.Key, pair.Value.GetType()).DefaultValue = pair.Value;

    // last column is computation result
    table.Columns.Add().Expression = formula;

    // result is the value of the last (computed) column
    return table.Rows.Add()[table.Columns.Count - 1];
  }
} 

用法:

var variables = new Dictionary<string, object> {
  { "d", 1},
  { "dft", 32},
  { "t", 4},
};

var result = Compute("d + dft-t", variables);

Console.Write(result);

结果:

29

如果你坚持字符串处理,你可以尝试正则表达式来替换智能

  using System.Text.RegularExpressions;

  ...

  var variables = new Dictionary<string, object> {
    { "d", 1},
    { "dft", 32},
    { "t", 4},
  };

  var formula = "d + dft-t";

  formula = Regex.Replace(
      formula,
    @"\b\p{L}[\p{L}\d_]*\b",
      m => variables.TryGetValue(m.Value, out var value) 
           ? value?.ToString() 
           : m.Value);

  Console.Write(formula);

结果:

1 + 32-4

模式解释:

\b          - word border
\p{L}       - letter (unicode one, we can use, say, cyrillic letters as well)
[\p{L}\d_]* - zero or more letters, digits, or _
\b          - word border

编辑:要从variables_cache 获取字典,您可以使用Linq

IDictionary<string, object> dict = variables_cache
  .ToDictionary(item => item.name, (object) (item.value));

从技术上讲,您不需要字典,可以轻松使用自己的结构:

// Assuming that MyVariable has Name and Value properties or fields
private static object Compute(string formula, 
                              IEnumerable<MyVariable> variables = null) {
  // using - don't forget to Dispose table which is IDisposable
  using (DataTable table = new DataTable()) {
    // If we have variables... 
    if (variables != null)
      foreach (var pair in variables) // ... we create columns 
        table.Columns.Add(pair.Name, pair.Value.GetType()).DefaultValue = pair.Value;

    // last column is computation result
    table.Columns.Add().Expression = formula;

    // result is the value of the last (computed) column
    return table.Rows.Add()[table.Columns.Count - 1];
  }
}

【讨论】:

  • 我使用了一个变量类的列表,有两个参数:name和value;某种方式来整合它而不用区分?,[我的问题中有更多细节,我已经编辑了它]
  • @Moix:是的,当然;请看我的编辑。在第一个代码示例中,您实际上不需要字典(我已经提供了它作为如何存储变量的示例)
猜你喜欢
  • 2011-05-10
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-10-13
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
相关资源
最近更新 更多