3

我正在开发一个接受数字字符串作为输入的 WinForms 应用程序。如果我的用户正在输入一个连续的数字范围,他/她可能会使用这样的速记符号来表示该范围:

12[3-5]5550[000-100]

使用该示例,我需要将该字符串扩展为它包含的整个数字范围,如下所示:

1235550000
1235550001
1235550002
..........
1235550100

1245550000
1245550001
1245550002
..........
1245550100

1255550000
1255550001
1255550002
..........
1255550100

除 0-9 外,字符串将仅包含 [、- 和 ],它们是用于表示范围的字符。作为将示例字符串扩展为单个数字的过程的一部分,我也想验证该字符串。例如,必须有相同数量的 [ 和 ] 字符。在括号内,范围中的第一个数字必须小于范围中的第二个数字。这些类型的东西。

是否存在执行这种字符串操作的现有模式?

4

3 回答 3

5

.net 中没有任何内置库可供您使用。考虑到您还需要验证,您的任务非常复杂。我创建了一个基于您的初始输入生成字符串的小型解决方案。请注意,这不是生产代码,我省略了一些检查。该代码仅显示了如何完成它的一种可能方式,并且可以接受批评。Token表示字符串的每个逻辑部分,在您的情况下是文字或范围说明符。

class Token
{
    public string Value { get; set; }

    public IEnumerable<string> GetAllValues()
    {
        if(IsRange(Value))
        {
            var rangeValues = Value.Split(new[] {'[', '-', ']'}, StringSplitOptions.RemoveEmptyEntries);
            //numeric format defines minimal string length. [01-10] will have numericFormat = "{0:00}"
            string numericFormat = CreateNumericFormat(rangeValues.ElementAt(0).Length);

            int[] ranges = rangeValues.Select(val => int.Parse(val)).ToArray();

            foreach (var val in GetRange(ranges[0], ranges[1]))
                yield return string.Format(numericFormat, val);
        }
        else
        {
            yield return Value;
        }
    }
    //validation is ommited
    private bool IsRange(string val)
    {
        return Value.Contains("-");
    }
    private string CreateNumericFormat(int minimalLength)
    {
        return "{0:"+new string('0', minimalLength)+"}";
    }
    private IEnumerable<int> GetRange(int minValue, int maxValue)
    {
        return Enumerable.Range(minValue, maxValue - minValue + 1);
    }
}

现在使用非常简单:

var initial = "12[05-10]3[008-010]";

var regularExp = @"\[\s*\d+\s*-\s*\d+\s*\]|\d+";

List<Token> tokens = new List<Token>();


foreach (Match match in Regex.Matches(initial , regularExp ))
{
    tokens.Add(new Token {Value = match.Value});
}


IEnumerable<string> result = new []{""};//empty source for start

foreach(var token in tokens)
{
    result = from v1 in result
             from v2 in token.GetAllValues()
             select v1 + v2;
}
//Dump is LinqPad specific call
result.Dump();

印刷:

12053008 
12053009 
12053010 
12063008 
12063009 
12063010 
12073008 
12073009 
12073010 
12083008 
12083009 
12083010 
12093008 
12093009 
12093010 
12103008 
12103009 
12103010 
于 2013-01-06T16:52:45.167 回答
2

解决方案可以分为两部分:

  • 提取将保持不变的输入部分: 您可以使用Regex.Split()实现此目的,并为匹配模式提供类似“[[0-9]+-[0-9]+]”的内容。这实际上会将您的输入拆分为仅包含常量的数组。
  • 执行相关范围的字典枚举。您可以查看一些代码示例:lexicographic permutation of the digits


  • 不幸的是,似乎没有任何直接的方法可以解决这个问题,您需要自己的逻辑

    于 2013-01-06T16:55:23.080 回答
    1

    是否存在执行这种字符串操作的现有模式?

    不,没有。

    您将需要为此构建自己的解析器 - 它需要考虑范围在字符串中的位置,并且您需要决定如何表示此结构 - 取决于使用情况(如果整数列表可能不起作用列表太长并且值不能用intor表示long)。

    于 2013-01-06T16:18:40.613 回答