まずListControl
、 がデータ ソースを参照する方法を変更します。結果IEnumerable<string>
を に変換していますList<string>
。特に、数文字しか入力していない場合、これは非効率的 (かつ不要) になる可能性があります。データの大規模なコピーを作成しないでください。
- (検索)
.Where()
から必要なものだけを実装するコレクションに結果をラップします。IList
これにより、文字を入力するたびに新しい大きなリストを作成する手間が省けます。
- 別の方法として、LINQを避け、より具体的な(そして最適化された)ものを書きます。リストをメモリに保持し、一致するインデックスの配列を作成し、配列を再利用して、検索ごとに再割り当てする必要がないようにします。
2 番目のステップは、小さなリストで十分な場合は、大きなリストを検索しないことです。ユーザーが「ab」と入力し始めて「c」を追加すると、大きなリストを調査する必要がなくなります。フィルタリングされたリストを検索するだけで十分です (そしてより高速です)。毎回完全な検索を実行しないでください。
3 番目のステップは難しいかもしれません。すばやく検索できるようにデータを整理します。ここで、データの格納に使用する構造を変更する必要があります。次のようなツリーを想像してください。
ABC
より良い天井を追加
骨の輪郭の上
これは単純に配列で実装できます (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) を構築することにより、バックトラックを回避します。これらは構築するのに費用がかかりますが (通常、powerset 構築を使用して作成されます)、非常に迅速に使用できます。
- スタブ: Knuth–Morris–Pratt は、検索する文字列を接尾辞として入力を認識する DFA を計算します。Boyer–Moore は、針の最後から検索を開始するため、通常、各ステップで針の長さ全体をジャンプできます。Baeza–Yates は、前の j 文字が検索文字列のプレフィックスであったかどうかを追跡するため、あいまい文字列検索に適応できます。bitap アルゴリズムは、Baeza-Yates のアプローチを応用したものです。
- インデックス メソッド: より高速な検索アルゴリズムは、テキストの前処理に基づいています。サフィックス ツリーやサフィックス配列などの部分文字列インデックスを作成すると、パターンの出現箇所をすばやく見つけることができます。
- その他のバリエーション: トリグラム検索などの一部の検索方法は、「一致/不一致」ではなく、検索文字列とテキストの間の「近さ」スコアを見つけることを目的としています。これらは「あいまい」検索と呼ばれることもあります。
並列検索について一言。可能ですが、並列化するためのオーバーヘッドが検索自体よりもはるかに高くなるため、簡単なことはめったにありません。検索自体を並行して実行することはしませんが (パーティショニングと同期はすぐに拡張しすぎて複雑になる可能性があります)、検索を別のスレッドに移動します。メイン スレッドがビジーでない場合、ユーザーは入力中に遅延を感じることはありません (リストが 200 ミリ秒後に表示されるかどうかは気にしませんが、入力してから 50 ミリ秒待たなければならない場合は不快に感じます)。 . もちろん、検索自体は十分に高速でなければなりません。この場合、スレッドを使用して検索を高速化するのではなく、UI の応答性を維持します。別のスレッドではクエリが作成されないことに注意してくださいUI がハングすることはありませんが、クエリが遅かった場合でも、別のスレッドでは遅くなります (さらに、複数の連続したリクエストも処理する必要があります) 。