First, I would change how ListControl sees your data source, you convert the result of IEnumerable<string> to List<string> . Especially when you have typed several characters, this can be inefficient (and unnecessary). Do not make expansive copies of your data .
- I would
.Where() result of .Where() in a collection that implements only what is required from IList (search). This will allow you to create a new large list for each character. - Alternatively, I would avoid LINQ, and I would write something more specific (and optimized). Keep your list in memory and create an array of matching indexes, reuse the array so you don't have to redistribute it for each search.
The second step is to not search the large list if that is enough. When the user starts typing “ab” and he adds “c”, you don’t need to search in a large list; searching in the filtered list is enough (and faster). Refine your search every time. Maybe don't do a full search every time.
The third step may be more difficult: save ordered data for quick retrieval . Now you need to change the structure that you use to store your data. imagine a tree:
Abc
Add better ceil
Above bone contour
This can be simply implemented using an array (if you work with ANSI names, otherwise the dictionary would be better). Create a list like this (goal illustration, it matches the beginning of the line):
var dictionary = new Dictionary<char, List<string>>(); foreach (var user in users) { char letter = user[0]; if (dictionary.Contains(letter)) dictionary[letter].Add(user); else { var newList = new List<string>(); newList.Add(user); dictionary.Add(letter, newList); } }
The search will be performed using the first character:
char letter = textBox_search.Text[0]; if (dictionary.Contains(letter)) { listBox_choices.DataSource = new MyListWrapper(dictionary[letter].Where(x => x.Contains(textBox_search.Text))); }
Please note that I used MyListWrapper() as suggested in the first step (but I briefly mentioned the second sentence for brevity, if you choose the right size for the dictionary key, you can keep each list short and fast so that you can possibly avoid or else). Also, note that you can try using the first two characters for your dictionary (more lists and shorter ones). If you continue this, you will have a tree (but I don’t think you have so many items).
there are many different algorithms for finding strings (with related data structures), just noting a few:
- Finite-based search based : in this approach, we avoid backtracking by creating a deterministic finite-state machine (DFA) that recognizes a stored search string. They are expensive to build — they are usually created using the poweret construct, but are used very quickly.
- Stubs : Knuth-Morris-Pratt calculates a DFA that recognizes entries with a search string as a suffix, Boyer-Moore starts a search from the end of the needle, so it can usually jump ahead the entire length of the needle at each step. Baeza-Yates keeps track of whether the previous j-characters were a search string prefix and, therefore, adapted to the search for fuzzy strings. The bit algorithm is an application of the Baeza-Yates approach.
- Index Methods : Faster search algorithms based on text preprocessing. After building a subscript index, such as a suffix tree or suffix array, pattern occurrences can be found quickly.
- Other options . Some search methods, such as trigram searches, are designed to look for "proximity" between the search string and text, rather than "match / inconsistency." They are sometimes called "fuzzy" searches.
A few words about parallel search. It is possible, but it is rarely trivial, because the overhead to make it parallel can be much higher than the search itself. I would not do the search on my own (separation and synchronization will soon become too expansive and possibly complicated), but I would move the search to a separate stream . If the main thread is not busy, your users will not experience any delays during their input (they will not notice if the list appears after 200 ms, but they will feel uncomfortable if they have to wait 50 ms after entering them), Of course, the search By itself, it should be fast enough, in this case you do not use streams to speed up the search, but save your user interface . Please note that a separate thread will not speed up your request , it will not hang the UI, but if your request was slow, it will still be slow in a separate thread (moreover, you will have to process several consecutive requests too).