web-dev-qa-db-ja.com

パフォーマンスを高速化するための比較手法のリスト

2つのリストの名前をクロスして、一方の名前のすべての出現をもう一方で見つける必要があります。リストは大きすぎます。1つは5万要素、もう1つは40万要素です。

小さなリストの場合、2つのforeachサイクルまたはLinqを使用しますが、プログラムを数日間実行できません。

高速比較を実行するためのアドバイスは何ですか?

編集:場合によっては、2番目のリストで出現する以上のものを見つける必要があります。つまり、すべての名前が繰り返され、異なる情報が関連付けられています。次に、2つのソースからの情報をマージすることを意図しています。

7
cap7

私の提案は、大きなリストをハッシュセットに丸呑みし、それを使用して小さなリストのアイテムを照合することです。

ハッシュセットは、配列のようなインデックス可能なメモリ構造に要素を格納する構造であり、要素の位置は、オブジェクトを使用して計算されたハッシュ値に等しくなります。つまり、ハッシュセット内の値を探すことは比較的高速な操作です。探しているオブジェクトのハッシュを計算し、そのインデックスに移動して、そこに格納されている実際のオブジェクトを確認します。これは、適切な実装では非常に小さな数になります(ハッシュセットの実装は、ハッシュのサイズのバランスを取る必要がありますしたがって、1次元要素の数、および衝突の数、したがって各要素の平均アイテム数)。

理想的には、ハッシュセットは一定のルックアップ時間に近づきます(具体的には[〜#〜] o [〜#〜](log2 ^ HN)ここで、Hはハッシュ関数のビットサイズです。したがって、すべてのN <2 ^ Hに対して、実質的に一定です)。したがって、全体として、マッチングアルゴリズムは線形複雑度に近づきます。 2つの主な欠点は、最初に組み込みの効率的な実装(JavaのHashMapが.NETのディクショナリクラスと同様にこの構造に基づいて構築されている)にアクセスしない限り、かなりのコードである独自のロールを実行する必要があることです。 、ハッシュセットは実際のメモリを大量に消費します。実装が期待される容量または実際の容量に基づいてハッシュ関数を変更しない限り、配列内に多くの空スペースがあることが実質的に保証されているためです。最初の次元が拡張され、2番目の次元の成長が制限されます)。

6
KeithS

効率的な並べ替えアルゴリズムを使用して両方のリストを並べ替えます(または、リストを作成した人/人がリストを「事前に並べ替え」ていることを確認してください)。

次に、両方のリストの最初の名前が同じである場合、一致が見つかりました。それ以外の場合は、「以前の」名前を破棄します。そして、リストの1つが空になるまでそれを行います。

粗雑な疑似コード:

    do {
        status = compare(shortList[i], longList[j]);
        if(status == EQUAL) {
            // Found match!
            i++;
            j++;
        } else if(status == EARLIER) {
            // No match, discard first entry in short list
            i++;
        } else {
            // No match, discard first entry in long list
            j++;
        }
    } while( (i < shortListEntries) && (j < longListEntries) );
6
Brendan

効率的な並べ替えアルゴリズムで小さなリストを並べ替え、大きなリストをトラバースし、大きなリストのすべてのアイテムについてバイナリ検索を使用して、小さなリストに一致するアイテムがあるかどうかを確認します。

2
Pieter B

あるセットで別のセットと一致するものを見つけてデータをマージすることは、リレーショナルデータベースが優れている点です。これが多くのことを行う必要がある場合は、選択したSQL DBのテーブルにリストをロードするのがおそらく最良のオプションです。

0
Ryathal