Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

P.S.: 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.

like image 689
indiantroy Avatar asked May 30 '26 10:05

indiantroy


1 Answers

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.

like image 187
rickster Avatar answered Jun 02 '26 03:06

rickster