我有一个由数对组成的数据结构,第一个是整数,第二个是字母数字字符串(可以用数字开头):
+--------+-----------------+
| Number | Name |
+--------+-----------------+
| 15 | APPLES |
| 16 | APPLE COMPUTER |
| 17 | ORANGE |
| 21 | TWENTY-1 |
| 291 | 156TH ELEMENT |
+--------+-----------------+
这些表格最多包含100,000行。
我想提供一个查找功能,用户可以在其中查找数字(就像它是一个字符串)或字符串片段。理想情况下,查找将在用户输入时“实时”;在每次击键之后(或者在短暂延迟~250-500 ms之后),将进行新的搜索以找到最可能的候选者。所以,例如搜索
1
将返回15 APPLES
,16 APPLE COMPUTER
,17 ORANGE
和
291 156TH ELEMENT
15
会将搜索范围缩小到15 APPLES
,291 156TH ELEMENT
AP
将返回15 APPLES
和16 APPLE COMPUTER
ELEM
将返回291 156TH ELEMENT
。我正考虑使用两个Dictionary<string, string>
,因为最终int
被比较为string
s - 一个将由整数部分索引,另一个将由字符串部分索引。
但是真正通过子串搜索不应该使用哈希函数,使用两倍于我觉得我应该需要的内存似乎很浪费。
最终的问题是,是否有任何表现良好的方法同时为两个大字符串搜索两个大型列表?
如果失败了,SortedDictionary
怎么样?可能会提高性能,但仍无法解决哈希问题。
考虑即时创建正则表达式,但我认为这会表现得非常糟糕。
我是C#的新手(来自Java世界)所以我还没有考虑过LINQ;是答案吗?
编辑18:21 EST :“名称”字段中的所有字符串都不会超过12-15个字符,如果这会影响您的潜在解决方案。
答案 0 :(得分:6)
如果可能的话,我会避免将所有100,000个条目加载到内存中。我会使用数据库或Lucene.Net来索引值。然后使用适当的查询语法有效地搜索结果。
答案 1 :(得分:3)
我考虑使用Trie数据结构。
如何实现?叶子代表你的“行”,但你会有“两条路径”到“行”的每个内存实例(一个用于数字,另一个用于名称)。
然后你可以牺牲自己的条件:
(ideally, but not required) ELEM will return 291 156TH ELEMENT.
或者为行实例提供更多路径。
答案 2 :(得分:1)
由于您正在搜索单词的开头,因此基于键的集合将不起作用,除非您存储所有可能的单词,例如“a”,“ap”,“app”,“appl”,“apple” 。
我的建议是将System.Collections.Generic.List<T>
与二进制搜索结合使用。您必须提供自己的IComparer<T>
,它也会找到单词的开头。您将使用两种数据结构。
一个List<KeyValuePair<string,int>>
持有单个字或数字作为键,数字作为值。
一个Dictionary<int,string>
持有全名。
你会这样做:
将您的句子(全名)分成单个单词。
将它们添加到列表中,并将单词作为键,并将数字作为KeyValuePair
的值。
将数字添加到列表中作为键和KeyValuePair
的值。
当列表已满时,对列表进行排序以允许二进制搜索。
搜索单词的开头:
将BinarySearch
与IComparer<T>
结合使用,在列表中进行搜索。
您从搜索中获得的索引可能不是第一个适用的索引,因此请返回列表,直到找到匹配的第一个条目。
使用列表中存储为值的数字,使用此数字作为键在字典中查找整个名称。