How to implement incremental search on a list

时间秒杀一切 提交于 2020-01-12 03:38:06

问题


I want to implement incremental search on a list of strings. Consider I have an array containing which contains the strings store,state,stamp,crawl,crow. My application has a text box in which the user enters the search string. Now, as the user enters the text, I need to highlight all the matches. For example, when the user enters "st" I need to highlight "Store,state,stamp" now when he types "a", I need to remove "Store" from the list.I am developing the application using c# with .net framework. What I plan to do is , on event on which text changes, I do a search in background and show the results. Is there any other way to solve this ?


回答1:


You could just look at the newly entered letter; if the new third letter is an 'a' just throw out all elements without 'a' at position three. If the user deletes a letter you have to rescan the whole original list and bring back all priviously removed items.

But what if the user pastes multiple letters from the clipboard, deletes multiple letters by selecting them, inserts or deletes a single or multiple letters somewhere in the middle?

You have just to many cases to watch for. You could do the method with the newly entered letter an fall back to a complete rescan if the search text changed in a way other than adding a single letter, but even this simple method is probably not worth the effort just to avoid a few ten or hundred string comparisons. As already mentioned, a Trie or Patricia trie is the way to go if you have really large data sets or want to be really quick.




回答2:


I've had to do something similar in the past, using a collection that contained approximately 500,000 words. I found that a directed acyclic word graph worked well. A DAWG has roughly the same performance as a trie, but will be more space efficient. It is, however, slightly more complex to implement.

Unfortunately, my work was in C, and I don't have a good reference for a DAWG implementation in C#.




回答3:


A trie data structure would scale well, if your list can grow to significant length (more than hundreds of entries). Check out e.g. this example implementation.




回答4:


Below is a function that will incrementally search a string for a substring to match.

public IEnumerable<int> FindAllMatches(string toMatch, string source) {
  var last = 0;
  do {
    var cur = source.IndexOf(toMatch,last);
    if ( cur < 0 ) {
      break;
    }
    yield return cur;
    last = cur + toMatch.Length;
  while(true);
}



回答5:


Instead of an array of strings you could use a generic collection. This way you can use the FindAll method with a delegate to search through the items.

string searchString = "s";
List<string> sl = new List<string>();
sl.Add("store");
sl.Add("state");
sl.Add("stamp");
sl.Add("crawl");
sl.Add("crow");
List<string> searchResults = sl.FindAll(delegate(string match) 
                                                { 
                                                    return   match.StartsWith(searchString, StringComparison.CurrentCultureIgnoreCase); 
                                                });



回答6:


Whoa...

Just use the builtin AutoComplete functionality on the textbox. You can provide it with your list of words and it will do the matching for you.




回答7:


Well, I have implemented a Trie and a DAWG for this problem and I stumbled upon 2 head scratchers:

1) DAWG --> Directed ACYCLIC Word Graph. How do you create this graph/traverse it with words like 'bot' and 'boot' the 'oo' in boot would cause a cycle based on a DAWG 2) A Trie eliminates this problem but then introduces some branch managing problems.

Constructing the graph is much easier (IMO) than actually using it to produce the words you want without also incurring more runtime.

I am still working on this.



来源:https://stackoverflow.com/questions/658235/how-to-implement-incremental-search-on-a-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!