确定double使用的字符数。Parse

时间:2018-09-20 18:48:48

标签: c# .net parsing

这是一个简单的问题,但是我找不到解决该问题的函数。我需要一种方法来确定使用多少个字符来解析字符串中的双精度数。

我想获取字符串的其余部分,并通过在符号字符串表中进行简单查找来使用它来确定其度量单位。


更新

我已将答案授予Olivier Jacot-Descombes,因为他拥有最完整的Regex,并用我自己的答案使用Regex击败了我。我看到的这个答案的唯一缺陷不是要考虑具有不同文化背景的逗号和点交换位置(尽管看起来有点混乱,但我在答案中确实考虑了这一点)。

但是,我将要实现的实际解决方案将不会使用Regex。我之所以仍然给予答案,是因为从本质上来说,我问的是错误的问题。我认为正则表达式的答案是我所问问题的最佳解决方案。

我想出的解决方案是迭代可用的单位,并使用inputStr.EndsWith(unitStr)与字符串进行比较,当我得到一个正匹配项时,我将立即减去该数字将知道多长时间测试字符串中的单位字符串的长度,然后我可以将double.Parse()与剩下的值一起使用(修剪后)。

5 个答案:

答案 0 :(得分:3)

您可以让Regex返回匹配项,这样就不需要两次通过。

var parseNumUnit = new Regex(
 @"(?<num>(\+|-)?([0-9,]+(\.)?[0-9]*|[0-9,]*(\.)?[0-9]+)((e|E)(\+|-)?[0-9]+)?)\s*(?<unit>[a-zA-Z]*)"
);

Match match = parseNumUnit.Match("+13.234e-3m");
string number = match.Groups["num"].Value; // "+13.234e-3" 
string unit = match.Groups["unit"].Value; // "m"

这里

(?<name>expression)    captures the expression in a group named "name".

我的数字正则表达式非常复杂,并且允许使用"+13.234e-3""12.34"".25""10.""23,503.14"之类的数字。如果您的数字格式更简单,则可以简化正则表达式。

答案 1 :(得分:0)

我建议您使用RegEx,如下所示:

(?<double>[\d.]+)(?<unit>.*)

匹配时,它将创建两个包含双精度值和单位的组“ double”和“ unit”。

示例:

1.25632 meter

此处double组将包含'1.25632',而unit组将包含'meter'

答案 2 :(得分:0)

我当前的解决方案是使用Regex解释浮点值,然后检索长度以知道单位从哪里开始。

    public static (double Value, string unit) Parse(string value)
    {
        var result = RegexParseDouble.Match(value);
        if(result.Success)
        {
            return (double.Parse(value.Substring(result.Length)), value.Substring(result.Length));
        }
        throw new FormatException("Value cannot be parsed as a floating point number.");
    }

    private static Regex RegexParseDouble
    {
        get => new Regex(
            @"^[-+]?(\d+" +
            Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator +
            @"\d+)*\d*(" +
            Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator +
            @")?\d+([eE][-+]?\d+)?");
    }

理想情况下,我宁愿不必自己解析该字符串,然后再让.NET再次解析该字符串以提供值。

答案 3 :(得分:0)

一个不涉及正则表达式的简单选项:

var input = "42,666 towels";

// Get a char[] of all numbers or separators (',' or '.', depending on language):
var numericChars = input
                    .TakeWhile(c => c == ',' || c == '.' || Char.IsNumber(c))
                    .ToArray();

// Use the chars to init a new string, which can be parsed to a number: 
var nr = Double.Parse(new String(numericChars));

// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();

// Outputs: Nr is 42,666, unit is towels.
Console.WriteLine($"Nr is {nr}, unit is {unit}.");

更新

作为对以下评论的回应,这里是扩展。我承认这破坏了上面一些优雅的简洁性,但是至少它是可读的,可配置的(可扩展的),并且可以正常工作:

var nrFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;

// Remove or add strings to this list as needed:
var validStrings = 
    new List<string>{ 
                    nrFormat.NaNSymbol, 
                    nrFormat.NegativeSign, 
                    nrFormat.NumberDecimalSeparator, 
                    nrFormat.PercentGroupSeparator, 
                    nrFormat.PercentSymbol, 
                    nrFormat.PerMilleSymbol, 
                    nrFormat.PositiveInfinitySymbol, 
                    nrFormat.PositiveSign
                };

validStrings.AddRange(nrFormat.NativeDigits);
validStrings.Add("^");
validStrings.Add("e");
validStrings.Add("E");
validStrings.Add(" ");


// You can use more complex numbers, like: 
var input = "-42,666e-3 Towels";

// Get all numbers or separators (',' or '.', depending on language):
var numericChars = input.TakeWhile(c => validStrings.Contains("" + c)).ToArray();

// Use the chars to init a new string, which can be parsed to a number: 
var nr = Double.Parse(new String(numericChars));

// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();

// Outputs is now: "Nr is -0,042666, unit is Towels"
Console.WriteLine($"Nr is {nr}, unit is {unit}.");

如您所见,输入现在可能要复杂得多。您甚至可以使用var input = "∞ Garden Gnomes";之类的东西,它将产生出色的输出:

  

Nr是∞,单位是花园侏儒。

答案 4 :(得分:0)

这是我想到的一种非Regex解决方案。如果可以保证您输入的内容始终采用数字-空格-单位的格式,则只需执行以下操作:

public static (double Value, string unit) Parse(string value)
{
    var values = value.Split(" ");

    double number;
    if (!double.TryParse(values[0], out number))
        throw new FormatException("Value cannot be parsed as a floating point number.");

    string unit = values[1];

    return (number, unit);
}

如果您输入的字符串格式是其他但一致的格式,则可以执行类似的操作来匹配该格式。