Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在具有通配符的集合中查找单词的最快方法_C#_Hashset - Fatal编程技术网

C# 在具有通配符的集合中查找单词的最快方法

C# 在具有通配符的集合中查找单词的最快方法,c#,hashset,C#,Hashset,我有大约200000个单词,我需要在这些单词中找到可以包含任意数量字母通配符的匹配项。我还需要一个选项来查找没有任何通配符的单词 我已按长度将单词分成了几个集合: static readonly HashSet<string>[] _validWords = { new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 3 letter words new HashSet<string>

我有大约200000个单词,我需要在这些单词中找到可以包含任意数量字母通配符的匹配项。我还需要一个选项来查找没有任何通配符的单词

我已按长度将单词分成了几个集合:

static readonly HashSet<string>[] _validWords = { 
    new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 3 letter words
    new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 4 letter words
    new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 5 letter words
    new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 6 letter words
    new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 7 letter words
    new HashSet<string>(StringComparer.OrdinalIgnoreCase), // 8 letter words
    new HashSet<string>(StringComparer.OrdinalIgnoreCase)  // 9 letter words
};
这是我当前使用正则表达式查找通配符单词的实现(最终我希望得到所有匹配的单词,但现在只查找一个(或没有)就可以了):

可以有任意数量的通配符(例如,所有字母都可以是通配符),但它目前的性能不如我所希望的那样好

所以我想知道是否有更有效的方法


谢谢你的帮助/建议

因为您的通配符只能匹配一个字母,所以问题并不太难。如果您需要支持可变长度的子字符串,我建议您阅读一些关于正则表达式工作原理的科学文献

这是一个相当基础的第二年comp sci“数据结构和算法”练习。在每个
节点中使用
字典
可能不是最快/最高效的内存。但我会这样处理这个问题

类节点
{
公共布尔结束语;
公共词典;
}
公共类词汇
{
私有节点根=新节点{endWord=false};
public const char通配符='";
public void DefineWord(字符串字)
{
var节点=根;
foreach(word中的变量c)
{
if(node.next==null)
node.next=新字典();
if(node.next.TryGetValue(c,out var nextNode))
{
node=nextNode;
}
其他的
{
node=node.next[c]=新节点{endWord=false};
}
}
node.endWord=true;
}
private bool有效(只读span word,Node)
{
if(word.IsEmpty&&node.endWord)
返回true;
if(node.next==null)
返回false;
if(字[0]==通配符)
{
word=word.Slice(1);
foreach(node.next.Values中的var n)
{
if(IsValid(字,n))
返回true;
}
}else if(node.next.TryGetValue(字[0],输出变量nextNode))
返回值是有效的(word.Slice(1),nextNode);
返回false;
}
公共bool有效(字符串字)
=>IsValid(字、根);
公共静态void Test1()
{
var单词=新单词();
文字。定义文字(“APE”);
文字。定义文字(“苹果”);
文字。定义文字(“熊”);
文字。定义沃德(“啤酒”);
文字。定义文字(“PEAR”);
文字。定义文字(“对等”);
文字。定义文字(“同行”);
Assert.True(words.IsValid(“APE”));
Assert.True(words.IsValid(“苹果”));
Assert.True(words.IsValid(“PEAR”));
Assert.True(words.IsValid(“PEER”);
Assert.True(words.IsValid(“PEERS”);
Assert.True(!words.IsValid(“钳子”));
Assert.True(words.IsValid(“PE_R”));
Assert.True(words.IsValid('u EAR');
Assert.True(words.IsValid(“_E_R”);
}
}

使用哈希集在这里没有任何好处。也许你需要找到一种可以搜索的树结构。“我尝试的实现不幸没有成功”——因为
HashSet
在这个场景中根本没有帮助,如果你提供一个适当的显示你尝试了什么,并详细解释它实际做了什么,你的问题会更好,您希望它做什么,以及具体需要什么帮助。@PeterDuniho-我是否错误地认为用于查找特定项的哈希集比迭代数组或列表更快?这是一个HashSet,因为它具有所需的功能,而不是复制数据,我正在寻找一个使用相同容器的解决方案。哈希集的查找速度更快,因为它不会遍历它的所有项:它使用正在查找的对象的哈希代码在哈希集中内部找到正确的分区,然后将每个项与匹配的哈希代码进行比较平等,直到找到问题所在。因此,与比较
.Count
项不同,您可能只比较1(取决于哈希代码冲突)。迭代哈希集并不比迭代数组或列表快,这正是您要做的。@Llama是的,这是我的理解,所以我使用哈希集,因为我确实需要查找特定的单词,另外我还需要查找通配符匹配。我已经用我当前的实现更新了这个问题,希望能更好地解释它。
public static bool IsValid(string word) {
    return word.Length >= GameplaySettings.Instance.MinWordLength && _validWords[word.Length - 3].Contains(word);
}
public static bool IsValidRegex(string pattern, int length) {
    pattern = $"^{pattern}$";

    foreach (string word in _validWords[length - 3]) {
        if (Regex.Matches(word, pattern, RegexOptions.Singleline).Count > 0) { return true; }
    }

    return false;
}