まずListControl
、データソースの表示方法を変更します。結果IEnumerable<string>
をに変換しList<string>
ます。特に、数文字を入力しただけの場合、これは非効率的(および不要)になる可能性があります。データの拡張コピーを作成しないでください。
.Where()
結果を、必要なものだけを実装するコレクションにラップします。IList
(検索)ます。これにより、入力する文字ごとに新しい大きなリストを作成する手間が省けます。
- 別の方法として、LINQを避け、より具体的な(そして最適化された)ものを作成します。リストをメモリに保持し、一致するインデックスの配列を作成し、配列を再利用して、検索ごとにリストを再割り当てする必要がないようにします。
2番目のステップは、小さいリストで十分な場合は大きいリストを検索しないことです。ユーザーが「ab」と入力し始め、「c」を追加すると、大きなリストを調べる必要はありません。フィルターされたリストで検索するだけで十分です(より高速です)。毎回絞り込み検索が可能です。毎回完全検索を実行しないでください。
3番目のステップは難しいかもしれません:データを整理してすばやく検索できるようにします。次に、データの保存に使用する構造を変更する必要があります。このような木を想像してみてください。
ABC
より良いCeilを追加する
骨の輪郭の上
これは単純に配列を使用して実装できます(ANSI名を使用している場合は、辞書の方が適しています)。次のようにリストを作成します(図の目的で、文字列の先頭に一致します)。
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);
}
}
次に、最初の文字を使用して検索が実行されます。
char letter = textBox_search.Text[0];
if (dictionary.Contains(letter))
{
listBox_choices.DataSource =
new MyListWrapper(dictionary[letter].Where(x => x.Contains(textBox_search.Text)));
}
MyListWrapper()
最初のステップで提案されたとおりに使用したことに注意してください(ただし、簡潔にするために2番目の提案では省略しました。辞書キーに適切なサイズを選択した場合は、各リストを短く高速に保つことができます。他のことは避けてください)。さらに、辞書に最初の2文字を使用しようとする場合があることに注意してください(リストが多く、リストが短い)。これを拡張すると、ツリーが作成されます(ただし、それほど多くのアイテムはないと思います)。
文字列検索(関連するデータ構造を含む)にはさまざまなアルゴリズムがありますが、ほんの数例です。
- 有限状態オートマトンベースの検索:このアプローチでは、保存された検索文字列を認識する決定性有限オートマトン(DFA)を構築することにより、バックトラックを回避します。これらは構築に費用がかかります(通常はパワーセット構造を使用して作成されます)が、非常にすばやく使用できます。
- スタブ:Knuth–Morris–Prattは、検索する文字列を接尾辞として入力を認識するDFAを計算します。Boyer–Mooreは針の端から検索を開始するため、通常、各ステップで針の長さ全体をジャンプできます。Baeza–Yatesは、前のj文字が検索文字列のプレフィックスであったかどうかを追跡するため、あいまい文字列検索に適応できます。bitapアルゴリズムは、Baeza–Yatesのアプローチを応用したものです。
- インデックス作成方法:より高速な検索アルゴリズムは、テキストの前処理に基づいています。接尾辞ツリーや接尾辞配列などの部分文字列インデックスを作成した後、パターンの出現をすばやく見つけることができます。
- その他のバリエーション:トライグラム検索などの一部の検索方法は、「一致/不一致」ではなく、検索文字列とテキストの間の「近さ」スコアを見つけることを目的としています。これらは「あいまい」検索と呼ばれることもあります。
並列検索についてのいくつかの単語。可能ですが、並列化するためのオーバーヘッドは検索自体よりもはるかに高くなる可能性があるため、簡単なことではありません。検索自体を並行して実行することはしませんが(パーティション分割と同期はすぐに拡張しすぎて複雑になる可能性があります)、検索を別のスレッドに移動します。メインスレッドがビジーでない場合、ユーザーは入力中に遅延を感じることはありません(200ミリ秒後にリストが表示されるかどうかはわかりませんが、入力後50ミリ秒待たなければならない場合は不快に感じます) 。もちろん、検索自体は十分に高速である必要があります。この場合、スレッドを使用して検索を高速化するのではなく、UIの応答性を維持します。別のスレッドではクエリが作成されないことに注意してくださいより高速で、UIはハングしませんが、クエリが遅い場合でも、別のスレッドでは遅くなります(さらに、複数の順次リクエストも処理する必要があります)。
HashSet<T>
文字列の一部を検索しているので、ここでは役に立ちません。