2011-05-01 95 views
1

考慮這個簡短的片段:如何在LINQ中執行此查詢?

var candidateWords = GetScrabblePossibilities(letters); 
var possibleWords = new List<String>(); 

foreach (var word in candidateWords) 
{ 
    if (word.Length == pattern.Length) 
    { 
     bool goodMatch = true; 
     for (int i=0; i < pattern.Length && goodMatch; i++) 
     { 
      var c = pattern[i]; 
      if (c!='_' && word[i]!=c) 
       goodMatch = false; 
     } 
     if (goodMatch) 
      possibleWords.Add(word); 
    } 
} 

是否有使用LINQ乾淨表達這樣一種方式?
這是什麼?

回答

3

一個簡單的翻譯就是使用Zip運算符將每個候選字覆蓋在模式字上。

var possibleWords = from word in candidateWords 
        where word.Length == pattern.Length 
         && word.Zip(pattern, (wc, pc) => pc == '_' || wc == pc) 
           .All(match => match) 
        select word; 

如果你真的想專注於指數,你可以使用Range操作:

var possibleWords = from word in candidateWords 
        where word.Length == pattern.Length 
         && Enumerable.Range(0, word.Length) 
            .All(i => pattern[i] == '_' 
              || pattern[i] == word[i]) 
        select word; 

編輯:

正如大衛·尼爾指出,Zip運營商不可用前.NET 4.0。然而,它自己實現它是trivial

+0

記住,'Zip'只會用C#4.0 – 2011-05-01 16:15:53

+0

工作'。所有()'返回一個布爾值,他需要一個列表。 – 2011-05-01 16:23:03

+0

@Paul:它是'where'子句的一部分。要將查詢物化爲列表,只需調用'ToList()'。 – Ani 2011-05-01 16:25:23

0

這樣做W/O拉鍊的另一種方式:

var possibleWords = candidateWords.Where(w => w.Length == pattern.Length && 
             word.Select((c, i) => pattern[i] == '_' || 
                   pattern[i] == c) 
              .All(b => b)) 
            .ToList();