Найдите в списке слова с буквами в определенных позициях

#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 at Idx и проверяем, соответствует Chr ли он в поисковом запросе