String replacement is unavoidable, but we can decrease the number of loops and replace operations by having a class to represent our expressions. When we have our arithmetic expressions wrapped in a reference type, we can add features and use them later:
public class ArithmeticExpression
{
public string Value;
public bool IsLiteral;
public bool IsFinalized;
public string ArithmeticSafeValue { get { return IsLiteral ? Value : "(" + Value + ")"; } }
public ArithmeticExpression(string value)
{
Value = value;
int dummy;
IsFinalized = IsLiteral = int.TryParse(value, out dummy);
}
}
And here is the methods to evaluate the final versions of our expressions, changing them to literals:
private static void Resolve(Dictionary<string, ArithmeticExpression> expressions)
{
foreach (string expressionKey in expressions.Keys.ToArray())
{
Resolve(expressionKey, expressions);
}
}
private static void Resolve(string expressionKey, Dictionary<string, ArithmeticExpression> expressions)
{
ArithmeticExpression expression = expressions[expressionKey];
if (expression.IsFinalized) return;
List<string> containedExpressions = expressions.Keys.Where(x => expression.Value.Contains(x)).ToList();
if (containedExpressions.Count > 0)
{
containedExpressions.ForEach((x) => Resolve(x, expressions));
containedExpressions.ForEach((x) => expression.Value = expression.Value.Replace(x, expressions[x].ArithmeticSafeValue));
expression.IsFinalized = true;
}
}
And here is how to use it:
public static void Main()
{
string exp1 = "10";
string exp2 = "20";
string exp3 = "exp1 + exp2 + 30";
string exp4 = "exp5 - exp3";
string exp5 = "exp3 / 10";
Dictionary<string, ArithmeticExpression> expressions = new Dictionary<string, ArithmeticExpression>();
expressions.Add("exp1", new ArithmeticExpression(exp1));
expressions.Add("exp2", new ArithmeticExpression(exp2));
expressions.Add("exp3", new ArithmeticExpression(exp3));
expressions.Add("exp4", new ArithmeticExpression(exp4));
expressions.Add("exp5", new ArithmeticExpression(exp5));
Resolve(expressions);
expressions.Keys.ToList().ForEach
(
(x) => Console.WriteLine("{0}: {1}", x, expressions[x].Value)
);
}
Hope this helps.