web-dev-qa-db-ja.com

正規表現一致のループ

これは私のソース文字列です:

<box><3>
<table><1>
<chair><8>

これは私の正規表現パターンです:

<(?<item>\w+?)><(?<count>\d+?)>

これは私のItemクラスです

class Item
{
    string Name;
    int count;
    //(...)
}

これは私のアイテムコレクションです。

List<Item> OrderList = new List(Item);

そのリストに、ソース文字列に基づいたアイテムを追加します。これが私の機能です。動いていない。

Regex ItemRegex = new Regex(@"<(?<item>\w+?)><(?<count>\d+?)>", RegexOptions.Compiled);
            foreach (Match ItemMatch in ItemRegex.Matches(sourceString))
            {
                Item temp = new Item(ItemMatch.Groups["item"].ToString(), int.Parse(ItemMatch.Groups["count"].ToString()));
                OrderList.Add(temp);
            }

Threreは、この例の文字を紛失するなどの小さな間違いである可能性があります。これは、これがアプリにあるものの簡単なバージョンだからです。

問題は、最終的にOrderListにアイテムが1つしかないことです。

[〜#〜] update [〜#〜]

うまくいきました。助けを求めています。

29
Hooch
class Program
{
    static void Main(string[] args)
    {
        string sourceString = @"<box><3>
<table><1>
<chair><8>";
        Regex ItemRegex = new Regex(@"<(?<item>\w+?)><(?<count>\d+?)>", RegexOptions.Compiled);
        foreach (Match ItemMatch in ItemRegex.Matches(sourceString))
        {
            Console.WriteLine(ItemMatch);
        }

        Console.ReadLine();
    }
}

3つの一致を返します。問題は他の場所にある必要があります。

43
mpen

今後の参考のために、LinqPadコードスニペットとして宣言型アプローチを使用するように変換された上記のコードを文書化します。

var sourceString = @"<box><3>
<table><1>
<chair><8>";
var count = 0;
var ItemRegex = new Regex(@"<(?<item>[^>]+)><(?<count>[^>]*)>", RegexOptions.Compiled);
var OrderList = ItemRegex.Matches(sourceString)
                    .Cast<Match>()
                    .Select(m => new
                    {
                        Name = m.Groups["item"].ToString(),
                        Count = int.TryParse(m.Groups["count"].ToString(), out count) ? count : 0,
                    })
                    .ToList();
OrderList.Dump();

出力あり:

List of matches

11
David Clarke

質問のタイトルだけに対処するには(「正規表現の一致をループする」)、次のことができます。

var lookfor = @"something (with) multiple (pattern) (groups)";
var found = Regex.Matches(source, lookfor, regexoptions);
var captured = found
                // linq-ify into list
                .Cast<Match>()
                // flatten to single list
                .SelectMany(o =>
                    // linq-ify
                    o.Groups.Cast<Capture>()
                        // don't need the pattern
                        .Skip(1)
                        // select what you wanted
                        .Select(c => c.Value));

これにより、キャプチャされたすべての値が単一のリストに「フラット化」されます。キャプチャグループを維持するには、SelectではなくSelectManyを使用してリストのリストを取得します。

5
drzaus