在某些位置带有字母的单词列表中查找
Find in the List of words with letters in certain positions
我正在做一个填字游戏。用户选择单词的单元格,程序从字典中编译一个填字游戏(所有可以在填字游戏中使用的单词)- List<string>
.
我需要在字典中找到匹配给定掩码(模式)的单词。
例如,我需要找到匹配
的所有单词
#a###g
模式,即字典中所有长度为 6
的单词,索引 1
处为 "a"
且索引 5
[=17= 处为 "g"
]
字母的数量和位置事先未知
如何实现?
I need to find a word in a list with "a" at index 1 and "g" at index 5, like the following
wordList.Where(word => word.Length == 6 && word[1] == 'a' && word[5] == 'g')
首先进行长度检查对于防止崩溃至关重要,除非您的单词按长度排列在不同的列表中..
如果您的意思是按字面意思将传递 "#a###g"
作为传达搜索词的参数:
var term = "#a###g";
var search = term.Select((c,i) => (Chr:c,Idx:i)).Where(t => t.Chr != '#').ToArray();
var words = wordList.Where(word => word.Length == term.Length && search.All(t => word[t.Idx] == t.Chr));
工作原理:
- 将“#a###g”投影到字符索引和字符本身的序列中,所以
('#', 0),('a', 1),('#', 2),('#', 3),('#', 4),('g', 5)
- 丢弃
'#'
,只留下('a', 1),('g', 5)
- 这意味着“'a' 在位置 1 和 'g' 在位置 5”
- 搜索词表,要求词长与"#a###g"相同,并且"从
word
中取出字符[=17]时,所有搜索词匹配=] 并检查它是否与搜索词 中的 Chr
匹配
可以转换文字说明(mask
)
#a###g
对应的正则表达式模式:
^\p{L}a\p{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, IEnumerable<string> availableWords) {
Regex regex = new Regex("^" + Regex.Replace(mask, "#*", m => @$"\p{{L}}{{{m.Length}}}") + "$");
return availableWords
.Where(word => regex.IsMatch(availableWords))
.OrderBy(word => 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
我正在做一个填字游戏。用户选择单词的单元格,程序从字典中编译一个填字游戏(所有可以在填字游戏中使用的单词)- List<string>
.
我需要在字典中找到匹配给定掩码(模式)的单词。
例如,我需要找到匹配
的所有单词#a###g
模式,即字典中所有长度为 6
的单词,索引 1
处为 "a"
且索引 5
[=17= 处为 "g"
]
字母的数量和位置事先未知
如何实现?
I need to find a word in a list with "a" at index 1 and "g" at index 5, like the following
wordList.Where(word => word.Length == 6 && word[1] == 'a' && word[5] == 'g')
首先进行长度检查对于防止崩溃至关重要,除非您的单词按长度排列在不同的列表中..
如果您的意思是按字面意思将传递 "#a###g"
作为传达搜索词的参数:
var term = "#a###g";
var search = term.Select((c,i) => (Chr:c,Idx:i)).Where(t => t.Chr != '#').ToArray();
var words = wordList.Where(word => word.Length == term.Length && search.All(t => word[t.Idx] == t.Chr));
工作原理:
- 将“#a###g”投影到字符索引和字符本身的序列中,所以
('#', 0),('a', 1),('#', 2),('#', 3),('#', 4),('g', 5)
- 丢弃
'#'
,只留下('a', 1),('g', 5)
- 这意味着“'a' 在位置 1 和 'g' 在位置 5”
- 搜索词表,要求词长与"#a###g"相同,并且"从
word
中取出字符[=17]时,所有搜索词匹配=] 并检查它是否与搜索词 中的
Chr
匹配
可以转换文字说明(mask
)
#a###g
对应的正则表达式模式:
^\p{L}a\p{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, IEnumerable<string> availableWords) {
Regex regex = new Regex("^" + Regex.Replace(mask, "#*", m => @$"\p{{L}}{{{m.Length}}}") + "$");
return availableWords
.Where(word => regex.IsMatch(availableWords))
.OrderBy(word => 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