2

を含む文字列変数があります [l=9;f=0;r=5;p=2]。複数ある場合があります:[l=9;f=0;r=5;p=2],[l=9;f=0;r=6;p=2]

Listを取得したいTuple<int,int,int>、どこでitem1 = value of l, item2= value of r, item3=value of p。これを行うための最良のアプローチは何ですか?
私のコード:

  // split string
    var splittedFormatedSeats = Regex.Matches(formatSeats, @"\[.+?\]")
                            .Cast<Match>()
                            .Select(m => m.Value)
                            .ToList();


     IList<Tuple<int,int,int>> fullSeat = new List<Tuple<int, int, int>>();
       foreach (var splittedFormatedSeat in splittedFormatedSeats)
       {

          ...
       }

ありがとう。

4

3 に答える 3

3

私は別の戦略を採用します。まず、文字列のサブコンポーネントを分割します

var components = formatSeats.Split(',');

これにより、文字列の配列が得られます。これは、大きな文字列の代わりに文字列の小さなチャンクを解析するのにはるかに効率的です。

次に、を使用Regexして値を抽出するか、次のような単純なコードを使用できます。

foreach(var component in components)
{
    var parts = component.Trim("[]".ToCharArray()).Split(';');

}

var results = from component in components
              let c = component.Trim("[]".ToCharArray())
                               .Split(';')
                               .Select(c=>int.Parse(c.SubString(2))
              select new { l = c[0], f=c[1], r=c[2], p = c[3] };

これにより、匿名タイプの列挙が生成されます。

foreach(var x in results)
{
    Console.WriteLine("{0} / {1} / {2} / {3}", x.l, x.f, x.r, x.p);
}

実際に必要な場合はTuple、コードを次のように変更するだけです。

var results = from component in components
              let c = component.Trim("[]".ToCharArray())
                               .Split(';')
                               .Select(c=>int.Parse(c.SubString(2))
              select new Tuple<int,int,int,int>{ l = c[0], f=c[1], r=c[2], p = c[3] };

ただし、コードを単純化し、読みやすさを向上させるために、小さな構造体を作成することをお勧めします。

public struct MyValue
{
     private readonly int m_L; 
     public int L { get {return m_L; } }

     private readonly int m_F; 
     public int F { get {return m_F; } }

     private readonly int m_R; 
     public int R { get {return m_R; } }

     private readonly int m_P; 
     public int P { get {return m_P; } }

     public MyValue(int l, int f, int r, int p)
     {
         m_L = l;
         m_F = f;
         m_R = r;
         m_P = p;
     }
}
....


var results = from component in components
          let c = component.Trim("[]".ToCharArray())
                           .Split(';')
                           .Select(c=>int.Parse(c.SubString(2))
          select new MyValue(c[0],c[1],c[2],c[3]);

最後に、文字列が常にこの形式である場合は、正規表現の使用を避けることができます。

于 2012-09-06T09:33:38.190 に答える
2
        string formattedString = "[l=9;f=0;r=5;p=2],[l=9;f=0;r=6;p=2]";
        var splitString = formattedString.Split(',')
                                    .Select(p => p.Trim(new char[]{'[',']',' '}));

        List<Tuple<int, int, int, int>> tupleList = new List<Tuple<int, int, int, int>>();
        foreach (var item in splitString)
        {
            int[] finalSplit = item.Split(';').Select(p => 
                                                      Convert.ToInt32(p.Substring(p.LastIndexOf('=')+1).Trim())
                                                      ).ToArray();
            tupleList.Add(new Tuple<int, int, int, int>(finalSplit[0], finalSplit[1],
                                    finalSplit[2], finalSplit[3]));
        }

これにより、l、f、r、およびpの値が分割され、タプルに追加されます。

于 2012-09-06T09:38:02.413 に答える
1

内部文字列の形式は常に同じですか?変数(l、f、r、p)ごとに常に1桁の値ですか?

もしそうなら、あなたはそれらを部分文字列にすることができます。

foreach(var splittedFormatedSeat  in splittedFormatedSeats)
{
    int x, y, z;
    string s = splittedFormatedSeat .ToString();
    if(int.TryParse(s[3].ToString(), out x) &&
       int.TryParse(s[11].ToString(), out y) &&
       int.TryParse(s[15].ToString(), out z))
       fullSeat.Add(new Tuple<int,int,int>(x,y,z));
}
于 2012-09-06T09:35:10.333 に答える