2012-01-13 33 views
5

Có cách nào khác để viết những điều sau đây không?Làm cách nào để tìm regex đầu tiên khớp với đầu vào của tôi trong danh sách các regex?

string input; 

var match = Regex.Match(input, @"Type1"); 

if (!match.Success) 
{ 
    match = Regex.Match(input, @"Type2"); 
} 

if (!match.Success) 
{ 
    match = Regex.Match(input, @"Type3"); 
} 

Về cơ bản, tôi muốn chạy chuỗi của mình thông qua một biểu thức của biểu thức và xem chuỗi nào biểu thị.

+4

Đặt regex trong danh sách rồi lặp lại qua danh sách đó cho đến khi bạn nhấn vào một danh sách. – CodesInChaos

+0

'Đặt các regex trong danh sách, và sau đó lặp lại danh sách đó cho đến khi bạn nhấn một .' hoặc viết một regex tốt hơn như' Type1 | Type2 | Type3' –

+0

@LB cách tìm ra phần nào của regex đã thành công khi bạn kết hợp họ? Giả sử các regex là không tầm thường. – CodesInChaos

Trả lời

0

Một cách khác để thực hiện điều đó. Nó lặp qua tất cả các danh sách, NHƯNG bạn có thể tìm một số hoặc chuỗi biến để khớp mà không cần phải viết x num nếu câu lệnh.

string input = "Type1"; 
List<string> stringsToTest = new List<string>() { @"Type1", @"Type2", @"Type3" }; 

var q = from string t in stringsToTest 
     where Regex.IsMatch(input, t) 
     select t; 

//This way you can get how many strings on the list matched the input 
foreach(string s in q) 
{ 
    Console.WriteLine(s); 
} 
+0

OP muốn biết cái nào khớp với nhau, không chỉ cái nào khớp với. – CodesInChaos

+0

Đúng, chỉ thay đổi. – H27studio

10
var patterns = new[] { "Type1", "Type2", "Type3" }; 
Match match; 
foreach (string pattern in patterns) 
{ 
    match = Regex.Match(input, pattern); 
    if (match.Success) 
     break; 
} 

hoặc

var patterns = new[] { "Type1", "Type2", "Type3" }; 
var match = patterns 
    .Select(p => Regex.Match(input, p)) 
    .FirstOrDefault(m => m.Success); 

// In your original example, match will be the last match if all are 
// unsuccessful. I expect this is an accident, but if you want this 
// behavior, you can do this instead: 
var match = patterns 
    .Select(p => Regex.Match(input, p)) 
    .FirstOrDefault(m => m.Success) 
    ?? Regex.Match(input, patterns[patterns.Length - 1]); 

Bởi vì LINQ to Objects sử dụng thực hiện chậm, Regex.Match sẽ chỉ được gọi cho đến khi một hợp được tìm thấy, vì vậy bạn không cần phải lo lắng về phương pháp này quá hăng hái.

+2

Tôi nghĩ bạn sẽ cần 'FirstOrDefault' vì nó có thể không được đảm bảo rằng ít nhất một đối sánh. – CodesInChaos

+0

@CodeInChaos: Tốt bắt, chỉnh sửa. –

+3

Một cũng có thể tạo danh sách các regex được biên dịch để có hiệu suất tốt hơn. – CodesInChaos

5

Vâng, tôi sẽ viết nó như thế này để tránh thực hiện các Regex trận đấu nhiều lần:

 match = Regex.Match(input, @"Type1|Type2|Type3"); 

     if (match.Success) 
     { 
      // loop, in case you are matching to multiple occurrences within the input. 
      // However, Regex.Match(string, string) will only match to the first occurrence. 
      foreach (Capture capture in match.Captures) 
      { 
       // if you care to determine which one (Type1, Type2, or Type3) each capture is 
       switch (capture.Value) 
       { 
        case "Type1": 
         // ... 
         break; 
        case "Type2": 
         // ... 
         break; 
        case "Type3": 
         // ... 
         break; 
       } 
      } 
     } 

Ngoài ra, nếu bạn có một danh sách tùy ý các mẫu mà bạn muốn kiểm tra:

 // assumption is that patterns contains a list of valid Regex expressions 
     match = Regex.Match(input, string.Join("|", patterns)); 

     if (match.Success) 
     { 
      // obviously, only one of these return statements is needed 

      // return the first occurrence 
      return match.Captures[0].Value; 

      // return an IEnumerable<string> of the matched patterns 
      return match.Captures.OfType<Capture>().Select(capture => capture.Value); 
     } 

Đây là một cách tiếp cận khác sử dụng các nhóm chụp được đặt tên để lập chỉ mục từng mẫu. khi tìm thấy một kết quả phù hợp, chúng tôi cố gắng xác định xem nhóm chụp nào đã được so khớp.

Tôi rất không thích mã này do sự nối không cần thiết lặp đi lặp lại của "mẫu" với chỉ số, nhưng tôi không chắc chắn làm thế nào để làm sạch này:

EDIT: Tôi đã dọn dẹp này mã một chút bằng cách sử dụng từ điển

 // assumption is that patterns contains a list of valid Regex expressions 
     int i = 0; 
     var mapOfGroupNameToPattern = patterns.ToDictionary(pattern => "Pattern" + (i++)); 

     match = Regex.Match(input, string.Join("|", mapOfGroupNameToPattern.Select(x => "(?<" + x.Key + ">" + x.Value + ")"))); 

     if (match.Success) 
     { 
      foreach (var pattern in mapOfGroupNameToPattern) 
      { 
       if (match.Groups[pattern.Key].Captures.Count > 0) 
       { 
        // this is the pattern that was matched 
        return pattern.Value; 
       } 
      } 
     } 
+0

Mã của bạn chỉ hoạt động vì các regex mẫu không chứa bất kỳ ký tự đại diện nào. Tôi cho rằng các regex thực sự không phải là tầm thường. – CodesInChaos

+0

@CodeInChaos - hmm, điểm công bằng. Tôi sẽ cố gắng giải quyết khả năng đó. –

+0

Nếu có vấn đề với mã của tôi hoặc cách tiếp cận của tôi, tôi sẽ đánh giá cao ý kiến. Tôi sẽ không yêu cầu mã này là tuyệt vời, nhưng theo như tôi biết (và từ thử nghiệm của riêng tôi) có vẻ như để có được công việc làm, và chỉ có một cuộc gọi đến Regex.Match lúc đó. Mặc dù tôi không chắc liệu vấn đề này có được giải quyết hiệu quả hơn hay không bằng cách kết hợp các mẫu vào một regex đơn (như ví dụ của tôi) hoặc bằng cách thực hiện nhiều kết quả regex (như các câu trả lời khác). Tò mò nếu có ai có ý kiến. –

Các vấn đề liên quan