简体   繁体   English

使用NSDictionary将索引存储为值,可以更快地进行NSArray查找

[英]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. 现在,当我从Web服务中获取所有学生的记录时,我有一个NSArray,可以存储所有学生的记录。 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. 假设我创建了一个名为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: 另外请假设在任何情况下都需要数组,并且为了快速查找,我还创建了其他字典,并将姓氏和id作为键和索引存储为上述值:

-(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? 我想知道在填充数组时创建多个词典是否明智,以便我可以通过拳头名,姓或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. PS:为简单起见,请考虑所有学生都有唯一的名字,姓氏和ID,因此在创建将名字,姓氏或ID作为值存储的词典时不会出现任何问题。

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 . 通常在Cocoa中,如果你发现自己正在为这个常见的任务咨询数据结构教科书,要么你错过了基础文档中的某些内容,要么你过早地进行了优化

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: 给定一组Student对象,至少有几种快速简便的方法可以获得具有唯一属性的对象:

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). 这两个都假设您的Student类已为这些字段声明了属性(或KVC兼容访问器)(即,不仅仅是实例变量)。

If you find yourself frequently accessing students by name, you might want to consider a dictionary mapping names to Student objects: 如果您发现自己经常按名称访问学生,您可能需要考虑将名称映射到Student对象的字典:

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 : 通过firstName查找学生:

Student * theStudent = [ studentsDictionary objectForKey:firstName ] ;

To get all Student objects from studentsDictionary , use 要从studentsDictionary获取所有Student对象,请使用

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 这假设你只会通过他们的firstName属性找到学生。但是@ rickster的解决方案通常会更好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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