標準実装B.Intersect(A).Count()
には、測定されたパフォーマンスの問題がない限り、短くて読みやすいという大きな利点があります。
パフォーマンスが導入可能な問題である場合HashSet<int>
、リソースの使用量と検索時間の点で適切な妥協点となります。ただし、パフォーマンスが心配なので、いくつかのテストを実行する必要があります (私が書いたこの無料のツールを使用しています)。
CPU: 1.8 GHz Pentium Core 2 Duo
反復回数: 100
各リストの項目数: 1000
A.Where(a => B.Contains(a)).Count()
: 8338 ティック
A.Intersect(B).Count()
: 288 ティック
B.Count - B.Except(A).Count()
: 313 ティック
テストで紹介しましょうHashSet<int>
(他の回答から実装を選択してください):
HashSet<int>
: 163 ティック
はるかに優れたパフォーマンスを発揮します。もっとうまくやれるでしょうか?入力範囲がわかっている (そして制限されている) 場合は、 を使用すると、これよりもはるかに優れた結果を得ることができますBitArray
。この例では、(簡単にするために) 正の数のみを想定していますが、簡単に適用できます。
public static int UseBitArray(int range, List<int> listA, List<int> listB) {
var BitArray array = new BitArray(range);
for (int i = 0; i < listA.Count; ++i)
array[listA[i]] = true;
int count = 0;
for (int i = 0; i < listB.Count; ++i) {
if (array[listB[i]])
++count;
}
return count;
}
それはどのように実行しますか?
BitArray
: 95 ティック
2 番目に良い方法 ( ) の 58% しかかかりませんHashSet<int>
。他人と比べることもしません。メモリを大量に使用し、広い範囲 (Int32.MaxValue / 2
たとえばInt32.MaxValue
、あなたは間違いなくそれと一緒に行くべきです。
また、入力についていくつかの仮定を行うことができれば、検索機能をさらに最適化できることにも注意してください (たとえば、セットが順序付けられていると仮定できる場合)。
スケールアップ方法 (Y 軸スケールは対数):
アイテムの数が増えた場合Except
よりもパフォーマンスが向上することに注意してください。Intersect
また、そのような些細なオブジェクト (整数) の場合、並行して実行してもパフォーマンスが向上しないことに注意してください (文字列の 2 つのリストの違いを見つけるも参照してください):非常に多数のアイテムに対して適切に調整されたアルゴリズムでない限り)。
パフォーマンスの向上の最後のビットを本当に探している場合は、独自のBitArray
クラスを実装することもできます (不要なものやエラーチェックなし):
sealed class FastBitArray {
public FastBitArray(int length) {
m_array = new int[((length - 1) / 32) + 1];
}
public bool this[int index] {
get {
return (m_array[index / 32] & (1 << (index % 32))) != 0;
}
set {
if (value)
m_array[index / 32] |= (1 << (index % 32));
else
m_array[index / 32] &= ~(1 << (index % 32));
}
}
private int[] m_array;
}
true
setter の内部には分岐があることに注意してください。分岐予測子にとってパターンは簡単 (常に) であるため、分岐を最適化する必要はありません。これよりも複雑にするパフォーマンスの向上はありません。
最新のテスト:
反復回数: 100
各リストの項目数: 1000000
HashSet<int>
: 144748 ティック
BitArray
: 37292 ティック
FastBitArray
: 28966 ティック
それらを視覚的に比較してみましょう (青色のシリーズは 1,000 項目でのテスト、オレンジ色のシリーズは 1,000,000、Y 軸は 1k のシリーズと簡単に比較できるように対数です)。遅いことがわかっているメソッドは単に省略されています。
1M シリーズのみを示す同じデータと線形 Y 軸: