Поиск NSArray для значения соответствия значения - PullRequest
22 голосов
/ 08 марта 2011

У меня есть NSArray objects, который имеет определенное свойство с именем name (тип NSString).
У меня есть второй NSArray из NSStrings, которые names.

I 'Я хотел бы получить NSArray из всех objects, чье свойство .name соответствует одному из names во втором NSArray.

Как мне это сделать, быстро и эффективно, так как это потребуетсядовольно часто.

Ответы [ 8 ]

72 голосов
/ 26 октября 2011

Почему бы не использовать предикаты, чтобы сделать это для вас?:

// 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];
14 голосов
/ 08 марта 2011

Вот простой способ:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", nameToFind];
[listOfItems filteredArrayUsingPredicate:predicate];
14 голосов
/ 08 марта 2011

С вашими текущими структурами данных вы можете сделать это только за 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];
        }
    }
}

(альтернативно, как предложено)Стефан: зациклите массив объектов и спросите массив имен, если он containsObject: для имени каждого объекта.)

Но если это действительно должно быть быстрее (действительно зависит от размера массивов каккак бы часто вы это не делали), вы можете улучшить это, введя NSDictionary, который отображает names в первом массиве на их объекты.Тогда каждый из этих поисков равен O (1), а общее время равно O (n).(Вы должны держать этот словарь всегда синхронизированным с массивом объектов, что не сложно с разумными средствами доступа. Этот метод также имеет ограничение, что один и тот же name не может появляться более чем на одном объекте.)

Альтернативный способ получения этого результата (и который не имеет этого последнего ограничения) состоит в том, чтобы использовать NSSet для вашей второй коллекции, а затем пройтись по массиву объектов, вызывая containsObject: с каждым на множествеимен.Насколько этот метод лучше, зависит от того, имеют ли ваши две коллекции примерно одинаковый размер, или одна из них намного больше другой.

6 голосов
/ 18 февраля 2015

Мне нравится использовать этот метод:

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...
}
2 голосов
/ 08 марта 2011

Наиболее полезными будут следующие методы:

filteredArrayUsingPredicate:

и

indexesOfObjectsPassingTest:

Второй использует кодовый блок, недоступный на iOS до 4.0

Оба они будут более эффективными, чем итерация напрямую.

Вот хороший пример: http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html

2 голосов
/ 08 марта 2011
NSMutableArray * foundNames = [NSMutableArray array];
for (MyObject * objectWithName in objectCollection) {
    if ([names containsObject:objectWithName.name]) {
        [foundNames objectWithName];
    }
}
0 голосов
/ 31 января 2015
int count=0;

if (range.location!=NSNotFound)
  {                   
  [searchindex addObject:[NSString stringWithFormat:@"%d",count]];           
  }
0 голосов
/ 08 марта 2011
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
       }
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...