#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();