2010-10-12 58 views
1

這個僞代碼的C#等價物是什麼?枚舉正則表達式匹配的名稱/值

var pattern = ...; 
var lookup = new Dictionary<string, string>(); 

foreach (var group in new Regex(pattern).Matches()) 
{ 
    lookup[group.Name] = group.Value; 
} 

我沒有看到任何暴露組名的組相關對象System.Text.RegularExpressions

我錯過了什麼?

什麼實際上,我試圖做的是轉換的文件在此格式的行:

eventName|message|date 

要將IEnumerable<EventLogLine>,與EventLogLine之中:

public struct EventLogLine 
{ 
    public string EventName { get; set; } 
    public string Message { get; set; } 
    public DateTime Date { get; set; } 
} 

並把這些行成IDictionary<string /*EventName*/, IEnumerable<EventLogLine>>.

回答

0

我只是在使用LINQ中敲了這個。它依靠List<string>填充文件中的行。

 var lines = new List<string>(); 
     var dict = lines.Select(l => 
     { 
      var sp = l.Split('|'); 
      return new EventLogLine { EventName = sp[0], Message = sp[1], Date = DateTime.Parse(sp[2]) }; 
     }) 
     .GroupBy(e => e.EventName) 
     .ToDictionary(grp => grp.Key, grp => grp.AsEnumerable()); 

基本上你的每一行轉換爲EventLogLine,使用Select(),然後使用GroupBy()根據事件名稱來創建分組,然後使用ToDictionary()運行查詢和創建你的字典中所要求的格式!

0

請參閱Match.Groups MSDN article.中的示例我認爲您應該看看Alastair的答案,雖然您的輸入非常簡單,但如果您只是使用ReadLine和Split,稍後可能會更容易閱讀代碼。

0

考慮使用ToLookup而不是ToDictionary。查找通常通過不可變的方式和暴露一個非常簡單的API來與linq和泛型代碼一起工作。另外,我會將解析封裝到EventLogLine結構中。

其結果是,代碼應該是這樣的:

IEnumerable<string> lines; 

ILookup<string, EventLogLine> lookup = 
    lines.Select(EventLogLine.Parse).ToLookup(evtLine => evtLine.EventName); 

一個例子消費:

if(lookup["HorribleEvent"].Any()) 
    Console.WriteLine("OMG, Horrible!"); 

foreach(var evt in lookup["FixableEvent"]) 
    FixIt(evt); 

var q = from evtName in relevantEventNames 
     from evt in lookup[evtName] 
     select MyProjection(evt); 

請注意,您不需要檢查鑰匙所有腦幹,不像一個字典:

if(dictionary.ContainsKey("HorribleEvent")) //&& dictionary["HorribleEvent"].Any() sometimes needed 
    Console.WriteLine("OMG, Horrible!"); 

if(dictionary.ContainsKey("FixableEvent")) 
    foreach(var evt in lookup["FixableEvent"]) 
     FixIt(evt); 

var q = from evtName in relevantEventNames.Where(dictionary.ContainsKey) 
     from evt in dictionary[evtName] 
     select MyProjection(evt); 

您可能注意到,使用包含IEnumerable值的字典引入了sub非常摩擦 - ILookup就是你想要的!

最後,修改後的EventLogLine

public struct EventLogLine { 
    public string EventName { get; private set; } 
    public string Message { get; private set; } 
    public DateTime Date { get; private set; } 

    public static EventLogLine Parse(string line) { 
     var splitline = line.Split('|'); 
     if(splitline.Length != 3) throw new ArgumentException("Invalid event log line"); 
     return new EventLogLine { 
      EventName = splitline[0], 
      Message = splitline[1], 
      Date = DateTime.Parse(splitline[2]), 
     }; 
    } 
} 
0

要回答你的問題,這部分:

我沒有看到任何 System.Text.RegularExpressions 組相關對象公開組名稱爲 。我錯過了什麼?

我已經適應了埃蒙Nerbonne的結構使用正則表達式:

public struct EventLogLine 
{ 
    public string EventName { get; private set; } 
    public string Message { get; private set; } 
    public DateTime Date { get; private set; } 

    private static Regex expectedLineFormat = new Regex(
      @"^(?<eventName>[^|]*)\|(?<message>[^|]*)\|(?<date>[^|]*)$", 
      RegexOptions.Singleline | RegexOptions.Compiled 
    ); 

    public static EventLogLine Parse(string line) { 

     Match match = expectedLineFormat.Match(line); 

     if (match.Success) { 
      return new EventLogLine { 
       EventName = match.Groups["eventName"].ToString(), 
       Message = match.Groups["message"].ToString(), 
       Date = DateTime.Parse(match.Groups["date"].ToString() 
      }; 
     } 
     else { 
      throw new ArgumentException("Invalid event log line"); 
     } 
    } 
} 
0

爲了更直接回答你原來的問題(沒有評論你的方法),因爲我有一個類似的問題...

根據Mono source codeGroups索引器的枚舉基於專用Match.regex字段,因此您需要仍然有Regex。但是,如果你這樣做,像你上面有...

public static Dictionary<string, string> ToDictionary(
    Regex regex, GroupCollection groups) 
{ 
    var groupDict = new Dictionary<string, string>(); 
    foreach (string name in regex.GetGroupNames()){ //the only way to get the names 
     Group namedGroup = groups[name]; //test for existence 
     if (namedGroup.Success) 
      groupDict.Add(name, namedGroup.Value); 
    } 
    return groupDict; 
} 

,或者作爲LINQ的,

regex.GetGroupNames() 
    .Where(name => groups[name].Success) 
    .ToDictionary(name => name, name => groups[name].Value)