简体   繁体   中英

Faster NSArray lookup using NSDictionary storing indices as values

Lets say I have a Student class as below:

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

Now when I get the records of all the students from a web service, I have an NSArray that stores records for all the students. At some point of time I need to look up the array to find a particular student's record based upon first name.

Assume I create a dictionary called studentsFirstNameDictionary.

So while adding objects to students array, I can do

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

I want to know if it is a good idea to create this dictionary to speed up the look up as below. Also please assume that in any case the array is required and for fast lookup I am creating other dictionaries too storing the last name and id as keys and indices as values like above:

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

Do you think this approach is performance wise better than having to iterate through the students array and compare the first name and return the matching student record?

I always need the students array because I need to populate a table view with that array. I am wondering if it is wise to create multiple dictionaries while populating the array so that I can look up a student record faster by fist name, last name or Id?

PS: For sake of simplicity, consider that all students have unique first name, last name and id so there will not be any issue while creating dictionaries storing first name, last name or ID as a value.

This sounds more complicated than it needs to be. Generally in Cocoa, if you find yourself consulting a data structures textbook for this common a task, either you've missed something in the Foundation docs or you're optimizing prematurely .

Given an array of Student objects, there are at least a couple of quick and easy ways to get the one with a unique attribute:

use a block test:

NSUInteger index = [studentArray indexOfObjectPassingTest:^(id obj, NSUInteger 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];

use a predicate:

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

Both of these assume your Student class has declared properties (or KVC-complient accessors) for those fields (that is, not just instance variables).

If you find yourself frequently accessing students by name, you might want to consider a dictionary mapping names to Student objects:

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

If you have a very large number of students and want to search them by various attributes, you might consider learning about Core Data.

I don't think you need the array at all.

Create your Student objects:

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

To look up a student by firstName :

Student * theStudent = [ studentsDictionary objectForKey:firstName ] ;

To get all Student objects from studentsDictionary , use

NSArray * allStudents = [ studentsDictionary allValues ] ;

This assumes you will only be finding students by their firstName attribute however.. @rickster's solution might be better in general

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM