4

いくつかの座標を含むファイルを読み取る必要があります。ファイルは次のように構成されています。

X1/Y1,X2/Y2,X3/Y3,X4/Y4

ここで、XとYは正の整数です。この問題を解決するために、正規表現を使用したいと思います(パターンが変更されたときのリファクタリングが最小限であるため、これは一般的には良い考えだと思います)。

したがって、私は次の正規表現を開発しました。

Regex r = new Regex(@^(?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+))(,(?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+)))*$");

ただし、この正規表現をデータでテストすると、たとえば次のようになります。

1302/1425,1917/2010

正規表現は、最後のX、Y、およびCoorグループのみを思い出すようです。この場合、Coorは「12/17」、Xは「1917」、Yは「2010」です。ある種の木を生成する方法はありますか?それで、各Coorの下にXおよびYコンポーネントがある、すべてのCoor式を提供するオブジェクトを見つけましたか?

可能であれば、1つの正規表現のみを使用したいと思います。これは、形式が別の正規表現に変更される可能性があるためです。

4

4 に答える 4

5

string.Splitandを使用すると、正規表現なしでこれを非常に簡単に解決できますint.Parse

var coords = s.Split(',')
    .Select(x => x.Split('/'))
    .Select(a => new {
        X = int.Parse(a[0]),
        Y = int.Parse(a[1])
    });

正規表現を使用して文字列を検証する場合は、次のように実行できます。

"^(?!,)(?:(?:^|,)[0-9]+/[0-9]+)*$"

データの抽出にも正規表現ベースのアプローチを使用する場合は、最初に上記の正規表現を使用して文字列を検証し、次に次のようにデータを追加します。

var coords = Regex.Matches(s, "([0-9]+)/([0-9]+)")
    .Cast<Match>()
    .Select(match => new
    {
        X = int.Parse(match.Groups[1].Value),
        Y = int.Parse(match.Groups[2].Value)
    });

本当に単一の正規表現で検証とデータ抽出を同時に実行したい場合は、2つのキャプチャグループを使用してCaptures、各グループのプロパティで結果を見つけることができます。単一の正規表現を使用して検証とデータ抽出の両方を実行できる1つの方法は次のとおりです。

List<Group> groups =
    Regex.Matches(s, "^(?!,)(?:(?:^|,)([0-9]+)/([0-9]+))*$")
         .Cast<Match>().First()
         .Groups.Cast<Group>().Skip(1)
         .ToList();

var coords = Enumerable.Range(0, groups[0].Captures.Count)
    .Select(i => new
    {
        X = int.Parse(groups[0].Captures[i]),
        Y = int.Parse(groups[1].Captures[i])
    });

ただし、このソリューションの複雑さがベースのソリューションと比較して価値があるかどうかを検討することをお勧めしますstring.Split

于 2010-10-13T20:22:31.450 に答える
3

このような単純な形式に正規表現を使用する理由はありません。

文字列を分割し、単純な文字列操作を使用して座標を取得するだけです。

var coordinates =
  fileContent.Split(',').Select(s => {
    int pos = s.IndexOf("/");
    return new {
      X = s.Substring(0, pos),
      Y = s.Substring(pos + 1)
    };
  });

ファイル形式がさらに複雑になった場合は、正規表現を使用するようにリファクタリングできます。それまでは、このような単純なコードは保守がはるかに簡単です。

于 2010-10-13T20:32:28.680 に答える
2

「Match」コマンドではなく「Matches」コマンドを使用すると、探しているものが得られる場合があります。また、正規表現をおそらくこれに短縮することはできません:

Regex(@"((?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+))|,)*");
于 2010-10-13T20:23:22.553 に答える
1

最初の問題は、正規表現に欠陥があり、アンカーがマッチングを破棄していることだと思います。これは私が思いついたものです:(ここに示されている正規表現だけで、コードはありません)

(?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+))

1つのMystagogueも同様に機能しますが、コンマに「空白」の一致を生成します(私にとって)。

于 2010-10-13T20:27:42.963 に答える