NSArrayにobjects
があり、name
(NSString型)という特定のプロパティがあります。
NSStringの2番目のNSArrayはnames
です。
すべてのobjects
のNSArrayを取得したいのですが、その.name
プロパティは、2番目のNSArrayのnames
のいずれかに一致します。
これは非常に頻繁に必要とされるため、どのようにすれば、迅速かつ効率的にこれを行うことができますか。
現在のデータ構造では、2番目の配列の各メンバーに対して最初の配列を1回ループすることにより、O(n ^ 2)時間内でしか実行できません。
NSMutableArray * array = [NSMutableArray array];
for (NSString * name in names) {
for (MyObject * object in objects) {
if ([[myObject name] isEqualToString:name]) {
[array addObject:object];
}
}
}
(Stefanが提案する代替案:オブジェクト配列をループ処理し、各オブジェクトの名前がcontainsObject:
かどうかを名前配列に尋ねます。)
しかし、これを本当に高速にする必要がある場合(実際に実行する頻度と同じくらいに配列のサイズに依存します)、最初の配列のnames
をそれらにマッピングするNSDictionaryを導入することでこれを改善できますオブジェクト。その後、これらの各ルックアップはO(1)であり、全体の時間はO(n)です(この辞書は常にオブジェクトの配列と同期している必要があります。合理的なアクセサーでは困難です。この手法には、同じname
が複数のオブジェクトに現れないという制約もあります。
この結果を取得する別の方法(および最後の制約を持たない)は、2番目のコレクションにNSSetを使用し、名前のセットのそれぞれでcontainsObject:
を呼び出すオブジェクト配列を調べます。この手法が優れているかどうかは、2つのコレクションがほぼ同じサイズであるか、一方が他方よりもはるかに大きいかどうかによって決まります。
なぜあなたのためにそれをするために述語を使うだけではありませんか?:
// For number kind of values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = %@", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];
// For string kind of values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];
// For any object kind of value (yes, you can search objects also):
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];
簡単な方法を次に示します。
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", nameToFind];
[listOfItems filteredArrayUsingPredicate:predicate];
私はこの方法を使用したい:
NSIndexSet *indexes = [_items indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return ((MyObject *)obj).name isEqualToString:name];
}];
if (indexes.count != 0) {
//extract your objects from the indexSet, and do what you like...
}
NSMutableArray * foundNames = [NSMutableArray array];
for (MyObject * objectWithName in objectCollection) {
if ([names containsObject:objectWithName.name]) {
[foundNames objectWithName];
}
}
最も役立つ方法は次のとおりです。
filteredArrayUsingPredicate:
そして
indexesOfObjectsPassingTest:
2つ目はコードブロックを使用しますが、4.0より前のiOSでは使用できません
これらは両方とも、直接反復するよりも効率的です。
ここに良い例があります: http://developer.Apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html
NSMutableArray* solutions = [NSMutableArray array];
for (Object* object in objects){
for (NSString* name in names){
if ([object.name isEqualToString:name]){
[solutions addObject:object];
break; // If this doesnt work remove this
}
}
}
int count=0;
if (range.location!=NSNotFound)
{
[searchindex addObject:[NSString stringWithFormat:@"%d",count]];
}