how to replace sections of string enclosed by square brackets with data stored in an array?

422 Views Asked by At

I have created a program which takes a string (e.g "[2*4]x + [3/2]x"), isolates all the instances where there is text within square brackets and places them within an array 'matches'. It then strips off the square brackets and by some function (i am using the library flee) takes each string (e.g 2*4) and evaluates it before storing it in an array 'answers'. I now need a way to replace the items within square brackets in the original string with the items in the 'answers' array but I am not sure how to do this

public string result(string solution,int num1, int num2, int num3,int num4)
{ 
    Regex regex = new Regex(@"\[.*?\]");
    MatchCollection matches = regex.Matches(solution);
    int count = matches.Count;
    int [] answers = new int [10];
    for (int i = 0; i <= count; i++)
    {
        string match = matches[i].Value;
        match = match.Replace("[", "");
        match = match.Replace("]", "");
        Console.WriteLine(match);
        ExpressionOptions options = new ExpressionOptions();
        options.Imports.AddType(typeof(System.Math));
        ExpressionOwner owner = new ExpressionOwner();
        owner.a = num1;
        owner.b = num2;
        owner.c = num3;
        owner.d = num4;

        Expression expressionmethod = new Expression(match, owner, options);

        try
        {
            ExpressionEvaluator<int> evaluator = (ExpressionEvaluator<int>)expressionmethod.Evaluator;
            int result = evaluator();
            answers[i] = result;
        }
        catch
        {
            ExpressionEvaluator<double> evaluator = (ExpressionEvaluator<double>)expressionmethod.Evaluator;
            double result = evaluator();
            answers[i] = Convert.ToInt32(result);
        }
    }
}
2

There are 2 best solutions below

3
Flynn1179 On BEST ANSWER

As well as getting the matches, use regex.Split with the same pattern to get the text between the matches.

Then it's just a case of interpolating them with your results to build your result string.

Right after MatchCollection matches = regex.Matches(solution); add the line:

string[] otherStuff = regex.Split(solution);
Debug.Assert(otherStuff.Length == matches.Count + 1); // Optional obviously. Regex can be weird though, I'd check it just in case.

Then you can just do

StringBuilder finalResult = new StringBuilder();
finalResult.Append(otherStuff[0]);
for (int i = 0; i < count; i++)
{
    finalResult.Append(answers[i]);
    finalResult.Append(otherStuff[i+1]);
}

and finalResult should give you what you need.

5
Wiktor Stribiżew On

You may use Regex.Replace with a callback method as the replacement argument where you may do whatever you need with the match value and put it back into the resulting string after modifications. Capture all text between square brackets so as to avoid extra manipulation with the match value.

Here is the code:

public string ReplaceCallback(Match m) 
{
    string match = m.Groups[1].Value;
    Console.WriteLine(match);
    ExpressionOptions options = new ExpressionOptions();
    options.Imports.AddType(typeof(System.Math));
    ExpressionOwner owner = new ExpressionOwner();
    owner.a = num1;
    owner.b = num2;
    owner.c = num3;
    owner.d = num4;

    Expression expressionmethod = new Expression(match, owner, options);

    try
    {
        ExpressionEvaluator<int> evaluator = (ExpressionEvaluator<int>)expressionmethod.Evaluator;
        int result = evaluator();
        return result.ToString();
    }
    catch
    {
        ExpressionEvaluator<double> evaluator = (ExpressionEvaluator<double>)expressionmethod.Evaluator;
        double result = evaluator();
        return result.ToString();
    }
}

public string result(string solution,int num1, int num2, int num3,int num4)
{
    return Regex.Replace(solution, @"\[(.*?)]", ReplaceCallback);
}

The \[(.*?)] regex matches [, then matches and captures any 0+ chars other than a newline as few as possible, and then matches a ] char. So, the text between [...] is inside match.Groups[1].Value that is further modified inside the callback method.