C# 键的适当数据结构。包含(x)映射/字典
我对这里的术语和解释的复杂性有些纠结,请随意编辑。C# 键的适当数据结构。包含(x)映射/字典,c#,algorithm,full-text-search,contains,containskey,C#,Algorithm,Full Text Search,Contains,Containskey,我对这里的术语和解释的复杂性有些纠结,请随意编辑。 我有1.000-2.000个对象。每一个都可以包含多个姓名词(第一、第二、中间、最后、标题…)和标准化数字(家庭、业务…、电子邮件地址,甚至物理地址和配偶姓名)。 我想实现一种搜索,使用户能够自由组合单词部分和数字部分。当我搜索“LL 676”时,我想找到包含任何带有“LL”和“676”的字符串的所有对象。 目前我正在迭代每个对象和每个对象属性,在“”上拆分searchString并执行stringInstance.Contains(searc
我有1.000-2.000个对象。每一个都可以包含多个姓名词(第一、第二、中间、最后、标题…)和标准化数字(家庭、业务…、电子邮件地址,甚至物理地址和配偶姓名)。
我想实现一种搜索,使用户能够自由组合单词部分和数字部分。
当我搜索“LL 676”时,我想找到包含任何带有“LL”和“676”的字符串的所有对象。
目前我正在迭代每个对象和每个对象属性,在“”上拆分searchString并执行stringInstance.Contains(searchword)。
这太慢了,所以我正在寻找更好的解决方案。
对此,什么是合适的语言无关数据结构?
就我而言,我需要它来做C#。
以下数据结构是一个好的解决方案吗?
它基于HashMap/字典。
首先,我创建了一个字符串,其中包含我要查看的所有姓名部分和电话号码,例如:“William Bill Henry Gates III 3.+436760000 BillGates Street 12”:
然后我在“”上拆分,为每个单词x创建fullfill x.contains(y)包含的所有可能的子字符串y。我将这些子字符串都放在hashmap/字典中。
在查找/搜索时,我只需要为每个搜索词调用搜索,并加入结果。当然,查找速度非常快(本机Hashmap/字典速度)。
编辑:插入也非常快(时间不重要),因为我使用了更智能的算法来获取子字符串。如果有人关心我的解决方案:
免责声明:
这只是一份草稿。
我只做了一些综合测试,我写了很多,没有再次测试。
我修改了我的代码:插入现在是((n^2)/2)+(n/2),而不是2^n-1,这是无限快的。单词长度现在不相关。
namespace MegaHash
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
public class GenericConcurrentMegaHash<T>
{
// After doing a bulk add, call AwaitAll() to ensure all data was added!
private ConcurrentBag<Task> bag = new ConcurrentBag<Task>();
private ConcurrentDictionary<string, List<T>> dictionary = new ConcurrentDictionary<string, List<T>>();
// consider changing this to include for example '-'
public char[] splitChars;
public GenericConcurrentMegaHash()
: this(new char[] { ' ' })
{
}
public GenericConcurrentMegaHash(char[] splitChars)
{
this.splitChars = splitChars;
}
public void Add(string keyWords, T o)
{
keyWords = keyWords.ToUpper();
foreach (string keyWord in keyWords.Split(splitChars))
{
if (keyWord == null || keyWord.Length < 1)
return;
this.bag.Add(Task.Factory.StartNew(() => { AddInternal(keyWord, o); }));
}
}
public void AwaitAll()
{
lock (this.bag)
{
foreach (Task t in bag)
t.Wait();
this.bag = new ConcurrentBag<Task>();
}
}
private void AddInternal(string key, T y)
{
for (int i = 0; i < key.Length; i++)
{
for (int i2 = 0; i2 < i + 1; i2++)
{
string desire = key.Substring(i2, key.Length - i);
if (dictionary.ContainsKey(desire))
{
List<T> l = dictionary[desire];
lock (l)
{
try
{
if (!l.Contains(y))
l.Add(y);
}
catch (Exception ex)
{
ex.ToString();
}
}
}
else
{
List<T> l = new List<T>();
l.Add(y);
dictionary[desire] = l;
}
}
}
}
public IList<T> FulltextSearch(string searchString)
{
searchString = searchString.ToUpper();
List<T> list = new List<T>();
string[] searchWords = searchString.Split(splitChars);
foreach (string arg in searchWords)
{
if (arg == null || arg.Length < 1)
continue;
if (dictionary.ContainsKey(arg))
foreach (T obj in dictionary[arg])
if (!list.Contains(obj))
list.Add(obj);
}
List<T> returnList = new List<T>();
foreach (T o in list)
{
foreach (string arg in searchWords)
if (dictionary[arg] == null || !dictionary[arg].Contains(o))
goto BREAK;
returnList.Add(o);
BREAK:
continue;
}
return returnList;
}
}
namespace MegaHash
{
使用制度;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用System.Threading.Tasks;
公共类GenericConcurrentMegaHash
{
//执行批量添加后,调用awaittall()以确保添加了所有数据!
私有ConcurrentBag=新ConcurrentBag();
私有ConcurrentDictionary=新ConcurrentDictionary();
/考虑将此更改为包括“--”。
公共字符[]拆分字符;
公共GenericConcurrentMegaHash()
:此(新字符[]{'})
{
}
公共GenericConcurrentMegaHash(字符[]拆分字符)
{
this.splitChars=splitChars;
}
公共空添加(字符串关键字,TO)
{
关键词=关键词.ToUpper();
foreach(关键字中的字符串关键字.Split(splitChars))
{
if(关键字==null | |关键字.Length<1)
返回;
this.bag.Add(Task.Factory.StartNew(()=>{AddInternal(关键字,o);}));
}
}
公共图书馆
{
锁(这个包)
{
foreach(任务t在包中)
t、 等待();
this.bag=新的ConcurrentBag();
}
}
专用void AddInternal(字符串键,ty)
{
for(int i=0;i
}我可能误解了您的算法或要求,但这似乎是一种潜在的性能改进:
foreach (string arg in searchWords)
{
if (String.IsNullOrEmpty(arg))
continue;
tempList = new List<T>();
if (dictionary.ContainsKey(arg))
foreach (T obj in dictionary[arg])
if (list.Contains(obj))
tempList.Add(obj);
list = new List<T>(tempList);
}
foreach(searchWords中的字符串arg)
{
if(String.IsNullOrEmpty(arg))
继续;
tempList=新列表();
if(dictionary.ContainsKey(arg))
foreach(字典[arg]中的tobj)
if(列表包含(obj))
圣殿骑士.Add(obj);
列表=新列表(圣堂武士);
}
我们的想法是,在此之前单独搜索第一个单词,并且只将所有后续单词放入searchWords列表中
这将允许您完全删除最终的foreach循环。结果只会保留在你的列表中,只要它们一直匹配每一个搜索词,而不是一开始就必须将匹配一个词的所有内容都放进去,然后在最后过滤掉 你写:任何带“LL”和“676”的字符串。你的意思是“和”在那里吗