3

入力として数値文字列を受け入れるWinFormsアプリに取り組んでいます。ユーザーが連続した範囲の数値を入力している場合、次のような省略表記を使用してその範囲を表すことができます。

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

その例を使用して、その文字列を次のように含む数値の全範囲に拡張する必要があります。

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

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

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

0〜9を除いて、文字列には、範囲を表すために使用される文字である[、-、および]のみが含まれます。例の文字列を個々の数値に拡張するプロセスの一環として、文字列も検証したいと思います。たとえば、[と]文字の数は同じでなければなりません。角かっこ内では、範囲の最初の数値は、範囲の2番目の数値よりも小さくする必要があります。これらの種類のもの。

この種の文字列操作を実行する既存のパターンはありますか?

4

3 に答える 3

5

あなたが使用できる.netのライブラリに組み込まれているものは何もありません。検証も必要であることを考えると、タスクは非常に複雑です。最初の入力に基づいて文字列を生成するための小さなソリューションを作成しました。これは製品コードではなく、いくつかのチェックを省略していることに注意してください。このコードは、実行方法の 1 つの可能な方法のみを示しており、批判の余地があります。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

このソリューションは、次の 2 つの部分に分けることができます。

  • 同じままである入力の一部を抽出する: Regex.Split() を使用してこれを実現し、"[[0-9]+-[0-9]+]" のような一致パターンを指定します。これにより、基本的に入力が定数のみを含む配列に分割されます。
  • 問題の範囲の辞書式列挙を実行します。いくつかのコードサンプルについては、これを見ることができます:数字の辞書式順列


  • 残念ながら、これを解決するための直接的なアプローチはないようで、独自のロジックが必要になります

    于 2013-01-06T16:55:23.080 に答える
    1

    この種の文字列操作を実行する既存のパターンはありますか?

    いいえ、ありません。

    このために独自のパーサーを作成する必要があります-文字列のどこに範囲があるかを考慮する必要があり、この構造を表す方法を決定する必要があります-使用法に応じて(整数のリストは、リストが長すぎて、値をintまたはで表すことができませんlong)。

    于 2013-01-06T16:18:40.613 に答える