Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSArray containsObject: faster alternative?

I did some runs on my iOS app with Instruments and I saw that 90% of the load on the main thread on launch (about 1000ms total) is caused by containsObject: calls. That's on the main thread and I don't think it's cool.

Is there a faster alternative to this method? An algorithm or another method?

Any suggestions?

MORE INFO:

  1. I looked into my code again I realized that in fact I don't need to know the order of the objects, only if an object is part of that set. Which means NSSet will do just fine (and I guess is faster).

  2. Number of objects - there may very well be 1000+ objects in that set.

like image 528
Nikolay Dyankov Avatar asked Feb 15 '13 12:02

Nikolay Dyankov


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.

Can NSArray contain nil?

arrays can't contain nil. There is a special object, NSNull ( [NSNull null] ), that serves as a placeholder for nil.

Is NSArray ordered?

In Objective-C, arrays take the form of the NSArray class. An NSArray represents an ordered collection of objects. This distinction of being an ordered collection is what makes NSArray the go-to class that it is.

How do you declare NSArray in Objective-C?

Creating NSArray Objects Using Array Literals In addition to the provided initializers, such as initWithObjects: , you can create an NSArray object using an array literal. In Objective-C, the compiler generates code that makes an underlying call to the init(objects:count:) method.


1 Answers

If you NEED to use an array, skip a bit further down


Alternate Options

Your other options might include:

  • Using an NSDictionary which uses key->value pairs which (I expect will) have O(1) read complexity at the cost of extra storage space for the keys

  • If you aren't using duplicates and order isn't important, using an NSSet will offer better read complexity (I don't know what the complexity will be, the docs probably will)


Using an Array

If you keep the array sorted, searching can be done in O(log n) time instead of O(n) as you can take advantage of a binary search.

Caveat Lector: This was written from memory

-(void) /*adding*/
{
    int proposedIndex = 0;
    proposedIndex = [array indexOfObject:node
                                inSortedRange:NSMakeRange(0, array.count)
                                      options:NSBinarySearchingInsertionIndex
                              usingComparator:
                      ^ NSComparisonResult(id obj1, id obj2)
                      {
                          if (obj1.valueToCompare < obj2.valueToCompare) return NSOrderedAscending;
                          if (obj1.valueToCompare > obj2.valueToCompare) return NSOrderedDescending;
                          else return NSOrderedSame;
                      }];

    [array insertObject:node atIndex:proposedIndex];
}


-(id) /* Getting */
{
    int location = [array indexOfObject:node
                                    inSortedRange:NSMakeRange(0, array.count)
                                          options:NSBinarySearchingFirstEqual
                                  usingComparator:
                          ^ NSComparisonResult(id obj1, id obj2)
                          {
                              if (obj1.valueToCompare < obj2.valueToCompare) return NSOrderedAscending;
                              if (obj1.valueToCompare > obj2.valueToCompare) return NSOrderedDescending;
                              else return NSOrderedSame;
                          }];
    if (location == NSNotFound) return nil;
    return [array objectAtIndex:location];
}
like image 154
James Webster Avatar answered Oct 13 '22 07:10

James Webster