如何在List<string>词库中查找匹配指定位置字符规则的单词?
填字游戏掩码匹配单词功能实现方案
核心实现逻辑
你需要的功能本质是模式匹配,核心逻辑如下:
- 先约定通配符(示例中用
#代表任意单个字符) - 先过滤掉长度和掩码不一致的单词,减少不必要的计算
- 仅对比掩码中固定字符的位置,通配符位置直接跳过,所有固定位置字符完全匹配的单词即为符合要求的结果
基础版实现(适合中小规模词库)
适合词库规模在万级以内的场景,代码简单易维护:
// 通配符定义,可根据业务需求自行修改 private const char WildcardChar = '#'; /// <summary> /// 从词库中匹配符合掩码的单词 /// </summary> /// <param name="mask">匹配掩码,如#a###g</param> /// <param name="wordLib">原始词库</param> /// <returns>所有符合条件的单词</returns> public List<string> MatchWordsByMask(string mask, List<string> wordLib) { var matchedWords = new List<string>(); int maskLength = mask.Length; // 提前提取掩码中的固定字符和对应下标,避免重复遍历 var fixedPositions = new List<(int index, char requiredChar)>(); for (int i = 0; i < maskLength; i++) { if (mask[i] != WildcardChar) { fixedPositions.Add((i, mask[i])); } } foreach (var word in wordLib) { // 长度不匹配直接跳过 if (word.Length != maskLength) continue; bool isMatch = true; // 仅校验固定位置字符 foreach (var pos in fixedPositions) { if (word[pos.index] != pos.requiredChar) { isMatch = false; break; } } if (isMatch) { matchedWords.Add(word); } } return matchedWords; }
调用示例:var result = MatchWordsByMask("#a###g", 你的词库变量);
优化版实现(适合大规模词库)
如果词库规模超过10万,可提前对词库按单词长度分组,避免每次查询遍历全量词库,性能提升非常明显:
// 全局缓存按长度分组的词库,程序启动时初始化一次即可 private Dictionary<int, List<string>> _lengthGroupedWordLib; private const char WildcardChar = '#'; /// <summary> /// 初始化词库分组 /// </summary> public void InitWordLib(List<string> originWordLib) { _lengthGroupedWordLib = originWordLib .GroupBy(word => word.Length) .ToDictionary(g => g.Key, g => g.ToList()); } /// <summary> /// 优化后的掩码匹配方法 /// </summary> public List<string> MatchWordsByMaskOptimized(string mask) { int maskLength = mask.Length; // 没有对应长度的单词直接返回空 if (!_lengthGroupedWordLib.TryGetValue(maskLength, out var sameLengthWords)) { return new List<string>(); } var fixedPositions = new List<(int index, char requiredChar)>(); for (int i = 0; i < maskLength; i++) { if (mask[i] != WildcardChar) { fixedPositions.Add((i, mask[i])); } } var matchedWords = new List<string>(); foreach (var word in sameLengthWords) { bool isMatch = true; foreach (var pos in fixedPositions) { if (word[pos.index] != pos.requiredChar) { isMatch = false; break; } } if (isMatch) { matchedWords.Add(word); } } return matchedWords; }
注意事项
- 如果需要不区分大小写匹配,对比字符时统一转为大写/小写即可,示例:
word[pos.index].ToString().ToLower()[0] != pos.requiredChar.ToString().ToLower()[0] - 若后续需要扩展更复杂的匹配规则(如某一位只能是元音、只能是数字等),仅需修改固定位置的校验逻辑即可,整体框架无需调整
内容的提问来源于stack exchange,提问作者Nizhgo
相关产品推荐
相关产品推荐

