2011-01-22 34 views
3

我有一个内存约10K对象的集合。我想让用户能够键入部分项目名称或描述并显示自动完成列表。什么是有效的方法来做到这一点?我真的需要尽可能快的响应时间,用户速度非常快。从.NET中的10000个项目中自动完成

非常感谢, 玛丽

+1

UI是用什么构建的? Windows Forms,WPF,一个来自ASP.Net的Web应用程序? – 2011-01-22 23:16:05

+0

这是ASP MVC应用程序,网页将通过控制器在按键JSONP上请求。 – 2011-01-23 00:27:48

回答

1

这不是一个.net特定的答案,但通常解决此问题的方法是创建一个索引并预先计算自动完成列表,这些列表存储在maps-of-maps-map- of-of-maps-of-lists结构(见下文)。它基本上是一个执行trie

基本上,你有一个哈希映射(REAL散列映射,以O(1)的实现),其中键是可能的子串。对于每个键字符串“XYZ”,它指向包含所有包含“XYZ”的对象的数据的映射;使用键“XYZA”,“XYZB”等...然后,一旦您达到N个字符(N个地图深),您的最后一个地图值就是包含该N个字符串的所有实际对象的列表。

然后你回顾一下你的集合,并且为每个对象计算长度为M到N的所有可能的子字符串(我假设你只想在输入> = M个字符时自动完成;太长的子字符串是无用的)地图。

的数据结构如下:

TopMap => { 
      'A' => Map_for_A 
      'B' => Map_for_B 
       ... 
      } 

Map_For_A => { 
      'AA' => Map_for_AA 
      'AB' => Map_for_AB 
       ... 
      } 
Map_For_AB => { 
      'ABC' => Map_for_ABC 
      'ABD' => Map_for_ABD 
       ... 
      } 
Map_For_ABD => { 
      'ABDE' => List_For_ABDE 
      'ABDX' => List_For_ABDX 
      } 
9

安排您的数据作为Trie

Trie

+4

具体而言,如果需要全文搜索,则使用后缀树:http://en.wikipedia.org/wiki/Suffix_tree – 2011-01-22 23:22:16

1

10'000个对象确实不多。

以下就足够了。

foreach(cItem Item in ItemList) 
{ 
    if(regex.match(Item.Name, "expression")) 
     //Add Item to autocomplete results; 


     //Break if more than 10 matches 

} 



for(i = 0; i < 10 && i < autocomplete_results.Length; ++i) 
{ 
      // display first 10 matches 
} 
0

通常你不希望给用户,例如每一种可能的选择 - 如果项目的列表是一组名称,输入字母“E”,并在其中获得每一个名字用E在下拉菜单中对于用户而言既不高效也不快速执行。您是否考虑过仅在用户输入3个(或更多)字符时提示结果?

如果这组项目是静态的,这将(可能)允许您预先计算每个独特的3或4个字符集的项目集,并将它们存储在列表字典中,如下所示:

Dictionary<String, List<Item>> itemsByKey; 
1

您可以使用Trie数据结构(或前缀树)来保存项目的名称。请参阅维基百科上非常详细的article,其中描述了此数据结构的原理并提供了一些基准测试结果。

Trie树的每个节点可以被实现为对应于各个数据串的第N位置时,其中N是节点的深度字符的排序列表。然后您可以使用binary search高效地执行数据查找。

,使其在工作你的情况,只是一味地对应于先前输入前缀的最后一个节点。当用户键入下一个字母时,只需搜索相应的直接子。各自的子树内

一切都是可能的匹配,因此可以提供给用户。为了使自动填充更加智能化,您可以跟踪各个数据项的频率并仅显示最常见的数据项。