Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# string convention parsing

Tags:

string

c#

parsing

I'm rather new to C# and have a user input string (valid I hope.)

This string will make up multiple sections and subsections of information.

For example:

1-7 will //represent values 1 2 3 4 5 6 7

3:.25:7 //will be the numbers contained between 3 and 7 in increments of .25 
        // (3 3.25 3.5 3.75 4 ... 6.75 7)
1,4,5  //will represent values 1 4 5

I would like to be able to iterate through a single string similar to this and get as many arrays out as there are data separated by a semicolon (;)

the main goal is to parse something like this:

1-7;3:.25:10;1,5,9;4-7

and since there are 4 "datasets" in the above, I should be creating 4 new arrays containing the values. If I had n "datasets" I should be creating n new arrays.

Later on I'd like to iterate through the arrays in a nested manner using all combinations.

Also if possible (not required) be able to do some sort of mixing of the representations like below:

1-7,9,16:2:20;

I hope what I am trying to accomplish here makes sense in my examples.

Thank you!


2 Answers

Well, there probably will be an answer with a clever RegEx, I'll give it a try with my favorite string.Split() function.

As a first step you can split the input string on ';'

string[] datasets = inputString.Split(';');

For as far as your last point goes, it seems that a comma ',' does more or less the same, you can merge that with Split(';', ',') or keep them separate with

string[] parts = datasets[i].Split(',');

A part is then one of three cases : single number, a range or a stepped range.

You can probe that with string.IndexOf() and/or

string[] rangeParts = parts[j].Split('-');
string[] steppedParts = parts[j].Split(':');

The results should have Length 2 and 3 respectively.

The resulting strings should then be checked with TryParse(), and because of the use of punctuation characters you'd better fix the Culture:

bool valid = double.TryParse(parts[k], 
  System.Globalization.NumberStyles.AllowDecimalPoint, 
  System.Globalization.CultureInfo.InvariantCulture, out value);

Those are the parts, some assembly required.

like image 164
Henk Holterman Avatar answered Oct 19 '25 06:10

Henk Holterman


Here's some C# code that should do what you want:

    var results = ParseExpression("1-7;3:.25:10;1,5,9;4-7");

    private static List<List<float>> ParseExpression(string expression)
    {
        // "x-y" is the same as "x:1:y" so simplify the expression...
        expression = expression.Replace("-", ":1:");

        var results = new List<List<float>>();
        foreach (var part in expression.Split(';'))
            results.Add(ParseSubExpression(part));

        return results;
    }

    private static List<float> ParseSubExpression(string part)
    {
        var results = new List<float>();

        // If this is a set of numbers...
        if (part.IndexOf(',') != -1)
            // Then add each member of the set...
            foreach (string a in part.Split(','))
                results.AddRange(ParseSubExpression(a));
        // If this is a range that needs to be computed...
        else if (part.IndexOf(":") != -1)
        {
            // Parse out the range parameters...
            var parts = part.Split(':');
            var start = float.Parse(parts[0]);
            var increment = float.Parse(parts[1]);
            var end = float.Parse(parts[2]);

            // Evaluate the range...
            for (var i = start; i <= end; i += increment)
                results.Add(i);
        }
        else
            results.Add(float.Parse(part));

        return results;
    }
like image 34
David Avatar answered Oct 19 '25 05:10

David