アレイだけを使用していない理由はありますか?int[]
パフォーマンスが向上します。また、リストに重複が含まれていると思います。そうでない場合は、セットを使用しているだけで問題はありません。
に追加すると、内容は(ほとんど)変更されないようHashSet
です。1日の終わりには、にフォールバックする比較機能を使用する必要がありますSequenceEqual
。しかし、毎回それを行う必要はありません。代わりに、または指数関数的な数のシーケンス比較を実行します(たとえば、ハッシュセットが大きくなるにつれて、SequenceEqual
既存の各メンバーに対して実行します)。適切なハッシュコードを事前に作成する場合、そのような比較をほとんど実行する必要がない場合があります。SequenceEqual
適切なハッシュコードを生成するオーバーヘッドは、おそらく、リストごとに1回だけ実行するのとほぼ同じです。
したがって、特定のを初めて操作するときはList<int>
、順序付けられた数列に基づいてハッシュを生成し、それをキャッシュする必要があります。次にリストを比較するときに、キャッシュされた値を使用できます。頭のてっぺんにある比較器(おそらく静的辞書?)を使ってこれをどのように行うかはわかりませんが、List
これを簡単に行うラッパーを実装することはできます。
これが基本的な考え方です。もろくないことを確認する必要があります(たとえば、メンバーが変更されたときにキャッシュされたハッシュコードを無効にすることを確認してください)が、それはあなたが使用している方法の典型的な状況になるとは思われませんこれ。
public class FasterComparingList<T>: IList<T>, IList, ...
/// whatever you need to implement
{
// Implement your interfaces against InnerList
// Any methods that change members of the list need to
// set _LongHash=null to force it to be regenerated
public List<T> InnerList { ... lazy load a List }
public int GetHashCode()
{
if (_LongHash==null) {
_LongHash=GetLongHash();
}
return (int)_LongHash;
}
private int? _LongHash=null;
public bool Equals(FasterComparingList<T> list)
{
if (InnerList.Count==list.Count) {
return true;
}
// you could also cache the sorted state and skip this if a list hasn't
// changed since the last sort
// not sure if native `List` does
list.Sort();
InnerList.Sort();
return InnerList.SequenceEqual(list);
}
protected int GetLongHash()
{
return .....
// something to create a reasonably good hash code -- which depends on the
// data. Adding all the numbers is probably fine, even if it fails a couple
// percent of the time you're still orders of magnitude ahead of sequence
// compare each time
}
}
リストを追加しても変更されない場合、これは非常に高速です。リストが頻繁に変更される可能性がある状況でも、新しいハッシュコードを作成する時間は、シーケンス比較を実行する場合とそれほど変わらない可能性があります(たとえあったとしても)。