Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSArray find object or objects - best practices [closed]

Solution: I have marked @BlackRider's answer as correct as it is the most versatile especially for complex comparisons however there are other very good answers and comments. I would encourage anyone with the same or similar question to review them and evaluate the best course of action for your specific situation.

In my situation, I am actually not using BlackRider's solution in my implementation. I have elected to use my own solution (see Edit #2 below) with help from @JoshCaswell's comments as well as @voromax's suggestion of indexesOfObjectsWithOptions:passingTest: due to the fact that my comparisons are very simple in this situation.

Thanks to everyone who answered and provided insight.


I am looking for an efficient way to retrieve an object from an NSArray based on a property of that object (a unique identifier, in this case). In C#.NET using Linq I would do something like

MyObject obj = myList.Single(o => o.uuid == myUUID); 

I am also wondering if there is an efficient way to get an array of objects matching a non-unique property. Again, with Linq it would look like

List<MyObject> objs = myList.Where(o => o.flag == true).ToList(); 

Of course I can write loops to do this but they would not be reusable and I'm suspicious of their performance.

Finding an object with a unique ID:

-(MyObject*)findObjectWithUUID:(NSString*)searchUUID{     for (MyObject* obj in _myArray){         if([obj.uuid isEqualToString: searchUUID])             return obj;     } } 

Finding an array of objects:

-(NSArray*)findObjectsWithFlag:(BOOL)f{     NSMutableArray* arr = [NSMutableArray array];     for (MyObject* obj in _myArray){         if(obj.flag == f)             [arr addObject:obj];     }     return arr; } 

-- EDIT --

Luckily in the first situation the object I am looking for has a unique identifier and I know there will only be one. I came up with a solution to implement isEqual on my object which will be invoked by indexOfObject:

- (BOOL)isEqual:(id)object{     return [self.uuid isEqualToString: ((MyObject*)object).uuid]; } 

And then create a "fake" lookup object and use that to find the real one

MyObject *lookupObject = [[MyObject alloc] init]; lookupObject.uuid = searchUUID; MyObject *actualObject =      [_myArray objectAtIndex:[_myArray indexOfObject:lookupObject]]; 

This is essentially the same as the for-in loop I posted above, but might be more readable & be more reusable. Of course, this only works for finding one unique object and does not address the second half of my question.

-- EDIT 2 --

Checking Class and implementing hash as recommended in comments.

- (BOOL)isEqual:(id)object{     return [object isKindOfClass:[MyObject class]] &&             [self.uuid isEqualToString: ((MyObject*)object).uuid]; }  - (NSUInteger)hash{     return [self.uuid hash]; } 
like image 823
Uptown Apps Avatar asked Nov 16 '13 22:11

Uptown Apps


People also ask

What's a difference between NSArray and NSSet?

The main difference is that NSArray is for an ordered collection and NSSet is for an unordered collection. There are several articles out there that talk about the difference in speed between the two, like this one. If you're iterating through an unordered collection, NSSet is great.

What is difference between NSArray and NSMutableArray?

The primary difference between NSArray and NSMutableArray is that a mutable array can be changed/modified after it has been allocated and initialized, whereas an immutable array, NSArray , cannot.

Can NSArray contain nil?

arrays can't contain nil.


1 Answers

You can use [NSPredicate], which gives you a query-like syntax for search. Check out this page for the predicate syntax description. Here's a simple example:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"propertyName == %@", @"value"]; NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate]; 

As to performance, I think your solution is OK since any search in an array needs to iterate through all the elements anyway, and then, for each object, compare the value of a field against the value you search for. You can optimize repeat searches within the same data, e.g. by creating and populating a dictionary that maps values of some field to the matching objects (or collections of objects, if the mapping is one to many).

like image 109
TotoroTotoro Avatar answered Sep 24 '22 05:09

TotoroTotoro