次のように、検索するオブジェクトを指定するセットを使用して実装すると便利な場合があります。
- (NSIndexSet *) indicesOfObjectsInSet: (NSSet *) set
{
if ( [set count] == 0 )
return ( [NSIndexSet indexSet] );
NSMutableIndexSet * indices = [NSMutableIndexSet indexSet];
NSUInteger index = 0;
for ( id obj in self )
{
if ( [set containsObject: obj] )
[indices addIndex: index];
index++;
}
return ( [[indices copy] autorelease] );
}
これには、配列内のすべてのオブジェクトを訪問する必要がありますが、少なくとも一度だけ訪問し、その間に高速な列挙を利用します。NSSet を使用し、そのセットに対して配列内の各オブジェクトをテストすることも、配列に含まれているかどうかをテストするよりもはるかに高速です。
ここには最適化の可能性がありますが、単一のオブジェクトが受信側の配列に複数回格納されている場合には機能しなくなります。
if ( [set containsObject: obj] )
{
[indices addIndex: index];
if ( [indices count] == [set count] )
break;
}
そうすれば、20'000 項目の配列をスキャンして 2 つのオブジェクトを取得し、それらが両方とも最初の 10 個の範囲内にある場合、配列内の他の 19'990 個のオブジェクトのスキャンを回避できます。私が言ったように、配列に重複が含まれている場合は役に立ちません.2つのインデックスが見つかるとすぐに停止するためです(両方が同じオブジェクトを指していても)。
そうは言っても、上記のマイクのコメントに同意します。最適化の時間が来ると、多少の苦痛に備えている可能性があります。さまざまなデータ型について考える価値があるかもしれません。たとえば、NSArray は単純なフラット コンテナーの最も論理的な選択肢のように見えますが、順序付け情報が実際に必要ない場合は、代わりに NSSet を使用することをお勧めします。これには、同じオブジェクト ( を使用して計算) を 2 回保存しないという追加の利点があります-isEqual:
。重複を追跡したいが順序付けは必要ない場合は、実際に重複を保存せずに各オブジェクトが追加/削除された回数を追跡することを除いて、NSSet として動作する NSCountedSet を使用できます。