Более быстрый поиск NSArray с использованием NSDictionary для хранения индексов в качестве значений

Допустим, у меня есть класс Student, как показано ниже:

class Student {
 NSNumber *id;
 NSString *lastName;
 NSString *firstName; 
}

Теперь, когда я получаю записи всех студентов из веб-службы, у меня есть NSArray, который хранит записи для всех учеников. В какой-то момент мне нужно найти массив, чтобы найти конкретную студенческую запись, основанную на имени.

Предположим, что я создаю словарь под названием studentsFirstNameDictionary.

Поэтому, добавляя объекты в массив учеников, я могу сделать

Student objStudent = [[Student alloc] init];
objStudent.Id = someId;
objStudent.firstName = someName;
objStudent.lastName = someLastName;
[studentsDictionary setValue:iterationCounter forKey:objStudent.firstName];
[students addObject:objStudent];

Я хочу знать, полезно ли создавать этот словарь для ускорения поиска, как показано ниже. Также предположим, что в любом случае массив необходим и для быстрого поиска я создаю другие словари, которые хранят последнее имя и id как ключи и индексы как значения, как указано выше:

-(Student*)getStudentByFirstName:(NSString *)firstName {
 int idxOfStudent = [ studentsDictionary valueForKey:firstName];
 return [students idxOfStudent];
}

Считаете ли вы, что этот подход эффективен по сравнению с тем, что нужно выполнить итерацию по массиву студентов и сравнить первое имя и вернуть соответствующую запись студента?

Мне всегда нужен массив студентов, потому что мне нужно заполнить табличный вид этим массивом. Мне интересно, нужно ли создавать несколько словарей при заполнении массива, чтобы я мог быстрее искать запись студента по имени, фамилии или имени?

P.S.: Для простоты рассмотрим, что все ученики имеют уникальное имя, фамилию и идентификатор, поэтому при создании словарей, хранящих имена, фамилию или идентификатор, не будет никаких проблем.

2 ответа

Я не думаю, что вам нужен массив вообще.

Создайте объекты-ученики:

Student objStudent = [[Student alloc] init];
objStudent.Id = someId;
objStudent.firstName = someName;
objStudent.lastName = someLastName;
[studentsDictionary setObject:student forKey:objStudent.firstName];

Чтобы посмотреть ученика на firstName:

Student * theStudent = [ studentsDictionary objectForKey:firstName ] ;

Чтобы получить все объекты Student из studentsDictionary, используйте

NSArray * allStudents = [ studentsDictionary allValues ] ;

Это предполагает, что вы будете находить студентов только по атрибуту firstName. Однако решение @rickster может быть лучше вообще


Это звучит сложнее, чем нужно. Как правило, в Cocoa, если вы обратитесь к учебнику по структурам данных для этой общей задачи, либо вы что-то пропустили в документах Foundation, либо вы преждевременно оптимизируется.

Учитывая массив объектов Student, есть, по крайней мере, несколько быстрых и простых способов получить тот, у которого есть уникальный атрибут:

используйте блок-тест:

********** index = [studentArray indexOfObjectPassingTest:^(id obj, ********** idx, BOOL *stop) {
 if ([obj.firstName isEqualToString:desiredFirstName]) {
 *stop = YES; // keeps us from returning multiple students with same name
 return YES;
 } else
 return NO;
}];
if (index != NSNotFound)
 Student *desiredStudent = [studentArray objectAtIndex:index];

использовать предикат:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstName LIKE %@", desiredFirstName];
NSArray *filteredArray = [studentArray filteredArrayUsingPredicate:predicate];
Student *desiredStudent = [lastObject]; // only object if we assume firstNames are unique

Оба из них предполагают, что ваш класс Student объявил свойства (или KVC-complient accessors) для этих полей (то есть не только переменные экземпляра).

Если вы часто обращаетесь к ученикам по имени, вы можете рассмотреть имена сопоставлений словаря с объектами Student:

NSMutableDictionary *studentsByName = [NSMutableDictionary dictionaryWithCapacity:[students count]];
for (Student *student in students)
 [studentsByName setObject:student forKey:[student firstName]];

Если у вас очень много учеников и вы хотите искать их по различным атрибутам, вы можете подумать об основных данных.

licensed under cc by-sa 3.0 with attribution.