首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析数字和数字范围列表的.NET正则表达式

解析数字和数字范围列表的.NET正则表达式
EN

Stack Overflow用户
提问于 2015-01-07 18:06:03
回答 1查看 435关注 0票数 1

我需要解析一个逗号分隔的数字和数字范围列表。这些字符串由用户输入到UI中,看起来类似于其中的一个(六个不同的示例输入):

代码语言:javascript
复制
1-3, 5, 7-10
1
21.1
1.2-3,5.1,7-10.1
1-3, 5.1, 7-10, 21
1.1-3.1,5.1,7.1-10.1

我的最终目标是有一个数字和数字范围的集合,我可以在下游处理。例如,在解析完前面的第一个字符串示例后,我的结果将是一个包含3个元素的集合: 1-3、5和7-10。

使用C#和.NET Regex,这种模式很好地用我需要的项填充了Matches集合(注意,使用了非捕获组):

代码语言:javascript
复制
(\d+(?:\.\d+)?-\d+(?:\.\d+)?)|(\d+(?:\.\d+)?)

不过,我有两个问题:

  1. 我需要在我的模式中所有这些,还是有可能有一个更简短的模式?
  2. 当字符串中包含无效字符时,是否可以在模式中添加一些内容来返回0匹配?例如,如果我在任何地方的字符串中都包含一个alpha字符,我就不希望出现匹配。现在,我通过两次传递来完成这个任务,一次是验证字符串是否只有有效的字符\d,.-,另一次是为了获得匹配,假设它在第一次传递中得到验证。

提前谢谢你的想法。

更新:

下面是我最后提出的解决方案(见@晓y 312回答):

代码语言:javascript
复制
public static IEnumerable<DataRange> ParseInput(string input)
{
    if (!Regex.IsMatch(input.Replace(" ", string.Empty), @"^[\d\.,\-]+$"))
        return Enumerable.Empty<DataRange>();

    return Regex.Matches(input.Replace(" ", string.Empty), 
        @"(?<A>\d+(?:\.\d+)?)(?:-(?<B>\d+(?:\.\d+)?))?").Cast<Match>()
        .Select(m => new DataRange
        {
            A = double.Parse(m.Groups["A"].Value,
                 System.Globalization.CultureInfo.InvariantCulture),
            B = m.Groups["B"].Success ? double.Parse(m.Groups["B"].Value, 
                 System.Globalization.CultureInfo.InvariantCulture) : (double?)null
        });

}

public class DataRange
{
    public double A;
    public double? B;
}

下面是示例用法:

代码语言:javascript
复制
static void Main(string[] args)
{
    Console.WriteLine("A\tB");
    var items = ParseInput("1");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
    items = ParseInput("21.1");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
    items = ParseInput("1-3,5,7-10");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
    items = ParseInput("1.2-3,5.1,7-10.1");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
    items = ParseInput("1-3, 5.1,  7-10,21");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
    items = ParseInput("1.1-3.1,5.1,7.1-10.1");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
    items = ParseInput("1.1-3.1,5.1,7.1-10.1a");
    Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
}

样本输出:

代码语言:javascript
复制
A       B
1
21.1
1       3
5
7       10
1.2     3
5.1
7       10.1
1       3
5.1
7       10
21
1.1     3.1
5.1
7.1     10.1
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-07 18:30:23

第一次仓促尝试:

代码语言:javascript
复制
public IEnumerable<object> ParseInput(string input)
{
    return Regex.Matches(input.Replace(" ", string.Empty), @"(?<A>\d+(\.\d+)?)(-(?<B>\d+(\.\d+)?))?").Cast<Match>()
        .Select(m => new
        { 
            A = m.Groups["A"].Value,  
            B = m.Groups["B"].Value
        });
}

固定:

代码语言:javascript
复制
public IEnumerable<DataRange> ParseInput(string input)
{
    if (!Regex.IsMatch(input.Replace(Environment.NewLine, string.Empty), @"^[\d\.,\- ]+$"))
        return Enumerable.Empty<object>();

    return input
        .Replace(" ", string.Empty)
        .Split(new[] { Environment.NewLine, "," }, StringSplitOptions.RemoveEmptyEntries)
        .Select(x => Regex.Match(x, @"(?<A>\d+(\.\d+)?)(-(?<B>\d+(\.\d+)?))?"))
        .Select(m => new DataRange
        {
            A = double.Parse(m.Groups["A"].Value, System.Globalization.CultureInfo.InvariantCulture),
            B = m.Groups["B"].Success ? double.Parse(m.Groups["B"].Value, System.Globalization.CultureInfo.InvariantCulture) : (double?)null
        });
}

public class DataRange
{
    public double A;
    public double? B;
}

投入:

代码语言:javascript
复制
    const string SampleInput = 
    @"1-3, 5, 7-10, 
1
21.1
1.2-3,5.1,7-10.1
1-3, 5.1, 7-10, 21
1.1-3.1,5.1,7.1-10.1";

产出:

代码语言:javascript
复制
A B
1 3 
5 null 
7 10 
1 null 
21,1 null 
1,2 3 
5,1 null 
7 10,1 
1 3 
5,1 null 
7 10 
21 null 
1,1 3,1 
5,1 null 
7,1 10,1 
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27825783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档