#c# #algorithm #linq #find
Вопрос:
Я занимаюсь составлением кроссвордов. Пользователь выбирает ячейки для слов, и программа составляет кроссворд из словаря (все слова, которые могут быть использованы в кроссворде) — Listlt;stringgt;
.
Мне нужно найти слово (слова) в словаре, которое соответствует заданной маске (шаблону).
Например, мне нужно найти все слова, которые соответствуют
#a###g
шаблон, т. е. все слова длины 6
в словаре с "a"
индексом at 1
и индексом "g"
at 5
Количество букв и их расположение заранее неизвестны
Как я это осознаю?
Комментарии:
1. Напишите какой-нибудь код. Когда у вас возникнут проблемы с вашим кодом, вернитесь и задайте вопрос
2. Если список слов не меняется, он относительно велик, и необходимо выполнить множество запросов с почти мгновенным ответом, я предлагаю создать словарь, в котором ключи-это буквы в позициях, а значения-это списки слов, которые удовлетворяют этой букве в этом конкретном индексе. Количество возможных ключей равно 26^(максимальное количество слов). Чтобы не занимать слишком много места, вы можете использовать ссылки в качестве значений слов. Тогда ответом на любую комбинацию букв является сочетание значений ключей для этих комбинаций буквенных индексов.
3. Давайте предположим, что у меня есть словарь, хранящийся в спискеlt;строкаgt;lt;строкаgt; — разве это не было
Listlt;Dictionarylt;...,...gt;gt;
бы тогда? и с какой целью?4. @user1984 Я не уверен, что стал бы беспокоиться об этом сразу; Я просто загрузил миллион идентификаторов guid в массив и LINQ, где они искали
'a'
[1]
и'b'
[5]
где ; 10 миллисекунд, включая время, необходимое для поиска ~ 4000 элементов5. да, верно. Это нужно проверить, если такая вещь необходима или нет. Хорошо, что ты это проверил. @CaiusJard
Ответ №1:
Вы можете преобразовать описание слова ( mask
)
#a###g
в соответствующий шаблон регулярного выражения:
^p{L}ap{L}{3}g$
Схема объяснена:
^ - anchor, word beginning p{L} - arbitrary letter a - letter 'a' p{L}{3} - exactly 3 arbitrary letters g - letter 'g' $ - anchor, word ending
а затем получите все слова из словаря, которые соответствуют этому шаблону:
Код:
using System.Linq; using System.Text.RegularExpressions; ... private static string[] Variants(string mask, IEnumerablelt;stringgt; availableWords) { Regex regex = new Regex("^" Regex.Replace(mask, "#*", m =gt; @$"p{{L}}{{{m.Length}}}") "$"); return availableWords .Where(word =gt; regex.IsMatch(availableWords)) .OrderBy(word =gt; word) .ToArray(); }
ДЕМОНСТРАЦИЯ:
string[] allWords = new [] { "quick", "brown", "fox", "jump", "rating", "coding" "lazy", "paring", "fang", "dog", }; string[] variants = Variants("#a###g", allWords); Console.Write(string.Join(Environment.NewLine, variants));
Исход:
paring rating
Комментарии:
1. @nizhgo: вы, вероятно, хотите иметь понятный пользовательский интерфейс, и берете все, что вводит пользователь, и динамически переводите это в регулярное выражение. Полагаться на то, что ваши пользователи придумают тарабарщину регулярных выражений, — плохая идея.
Ответ №2:
Мне нужно найти слово в списке с «а» в индексе 1 и «г» в индексе 5, как показано ниже
wordList.Where(word =gt; word.Length == 6 amp;amp; word[1] == 'a' amp;amp; word[5] == 'g')
Сначала проверка длины будет иметь решающее значение для предотвращения сбоя, если только ваши слова не будут расположены в разных списках по длине..
Если вы имеете в виду, что вы буквально передадите "#a###g"
в качестве параметра, передающего поисковый запрос:
var term = "#a###g"; var search = term.Select((c,i) =gt; (Chr:c,Idx:i)).Where(t =gt; t.Chr != '#').ToArray(); var words = wordList.Where(word =gt; word.Length == term.Length amp;amp; search.All(t =gt; word[t.Idx] == t.Chr));
Как это работает:
- Возьмите «#a###g» и проецируйте его на последовательность индекса символа и самого символа, так что
('#', 0),('a', 1),('#', 2),('#', 3),('#', 4),('g', 5)
- Отбросьте
'#'
, оставив только('a', 1),('g', 5)
- Это означает «»а» в позиции 1 и»г» в позиции 5″.
- Выполните поиск по списку слов, требуя, чтобы длина слова была такой же, как «#a###g», а также чтобы все поисковые запросы совпадали, когда мы «извлекаем символ из
word
atIdx
и проверяем, соответствуетChr
ли он в поисковом запросе