Как выполнить этот запрос в LINQ?

#c# #linq

#c# #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 amp;amp; goodMatch; i  )
        {
            var c = pattern[i];
            if (c!='_' amp;amp; word[i]!=c)
                goodMatch = false;
        }
        if (goodMatch)
            possibleWords.Add(word);
    }
}
  

Есть ли способ выразить это чисто с помощью LINQ?
Что это?

Ответ №1:

Простым переводом было бы наложение каждого слова-кандидата на слово-шаблон с помощью Zip оператора.

 var possibleWords = from word in candidateWords
                    where word.Length == pattern.Length
                       amp;amp; 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
                       amp;amp; Enumerable.Range(0, word.Length)
                                    .All(i => pattern[i] == '_' 
                                           || pattern[i] == word[i])
                    select word;
  

Редактировать:

Как указывает Дэвид Нил, Zip оператор недоступен до .NET 4.0. Однако это тривиально реализовать самостоятельно.

Комментарии:

1. .All() возвращает логическое значение, ему нужен список.

2. @Paul: Это часть where предложения. Чтобы материализовать запрос в список, просто вызовите ToList() .

Ответ №2:

Другой способ сделать это без Zip:

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