Schiavini
Schiavini

Reputation: 2939

Parsing measurement units

I have the following string:

string value = "123.456L";

What is the best way to parse this string into a string and a double:

double number = 123.456;
string measure = "L"

Instead of the L, we could also have something else, like oz, m/s, liter, kilograms, etc

Upvotes: 4

Views: 3770

Answers (7)

angularsen
angularsen

Reputation: 8668

You might want to take a look at Units.NET on GitHub and NuGet. It supports parsing abbreviations in different cultures, but it is still on my TODO list to add support for parsing combinations of numbers and units. I have already done this on a related project, so it should be straight-forward to add.

Update Apr 2015: You can now parse units and values by Length.Parse("5.3 m"); and similar for other units.

Upvotes: 1

djole351
djole351

Reputation: 11

You can try this:

string ma = Regex.Match(name, @"((\d\s)|(\d+\s)|(\d+)|(\d+\.\d+\s))(g\s|kg\s|ml\s)").Value;

this will match:

40 g , 40g , 12.5 g , 1 kg , 2kg , 150 ml ....

Upvotes: 0

Shegit Brahm
Shegit Brahm

Reputation: 717

Simply spoken: look for all characters that are 0..9 or . and trim them to a new string, then have last part in second string. In a minute I cann give code.

Edit: Yes, I meant digits 0-9, corrected it. But easier is to get index of last number and ignore stuff before for the trimming.

Upvotes: 0

Jetti
Jetti

Reputation: 2458

You could do it with a regex

        using System.Text.RegularExpression;
        Regex reg = new Regex(@"([\d|\.]*)(\w*)");
        string value = "123.4L";
        MatchCollection matches = reg.Matches(value);
        foreach (Match match in matches)
        {
            if (match.Success)
            {

                GroupCollection groups = match.Groups;
                Console.WriteLine(groups[1].Value); // will be 123.4
                Console.WriteLine(groups[2].Value); // will be L

            }
        }

So what this will do is look for a 0 or more digits or "." and then group them and then look for any character (0 or more). You can then get the groups from each match and get the value. This will work if you want to change the type of measurement and will work if you don't have a decimal point either.


Edit: It is important to note that you must use groups[1] for the first group and groups[2] for the second group. If you use group[0] it will display the original string.

Upvotes: 1

xxbbcc
xxbbcc

Reputation: 17346

I'd do it like this:

public bool TryParseUnit ( string sValue, out double fValue, out string sUnit )
{
    fValue = 0;
    sUnit = null;

    if ( !String.IsNullOrEmpty ( sValue ) )
    {
        sUnit = GetUnit ( sValue );

        if ( sUnit != null )
        {
            return ( Double.TryParse ( sValue.Substring ( sValue.Length - sUnit.Length ),
                out fValue );
        }
    }

    return ( false );
}

private string GetUnit ( string sValue )
{
    string sValue = sValue.SubString ( sValue.Length - 1 );

    switch ( sValue.ToLower () )
    {
        case "l":
            return ( "L" );
    }

    return ( null );
}

I know it's more complicated than the other answers but this way you can also validate the data during parsing and discard invalid input.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726909

Assuming that the units of measure are always expressed as a single character at the back of the string, you can do this:

string value = "123.456L";
var pos = value.LastIndexOfAny("0123456789".ToCharArray());
double number = double.Parse(value.Substring(0, pos+1));
string measure = value.Substring(pos+1);

Upvotes: 9

Yuriy Faktorovich
Yuriy Faktorovich

Reputation: 68717

Based on the comment explaining the input, I'd use Regex.

double number = double.Parse(Regex.Match(value, @"[\d.]+").Value);
string measure = value.Replace(number.ToString(), "");

The regex [\d.] will match any number or ., the + means it must be for 1 or more matches.

Upvotes: 7

Related Questions