16

I have a NSMutableArray of NSNumbers. Basically I just want to check if any of the NSNumbers in the array = some value.

I could iterate through the array, checking one by one, by this is by no means optimal.

I also tried and failed using containsObject, because this only works if the id's are the same.

I read something about NSPredicate, this seems like a good solution, but I am not sure on how to use it with an NSArray.

Any answer is appreciated.

Thanks

Legolas
  • 12,145
  • 12
  • 79
  • 132
Henry
  • 183
  • 1
  • 1
  • 4
  • If your array is unsorted there is no more effecient way than O(n) to check what you want and the iterating does that. Any other way will first have to sort the array (O(nlogn)) before it can search it more efficiently (O(logn)) – dtech Aug 07 '11 at 06:56
  • The array isn't sorted using any sorting methods, but the manner I'm adding objects to it, the array is already in numerical order. How does it being sorted help? – Henry Aug 07 '11 at 07:34
  • 1
    If it is sorted you can binary search it with O(logn) speed – dtech Aug 07 '11 at 08:24

6 Answers6

20

Inspired by bernstein I looked up some more info about the and i found CFArrayContainsValue

BOOL CFArrayContainsValue(CFArrayRef theArray, CFRange range, const void *value);

Example:

NSArray *numbers;
NSNumber *value;
BOOL found = CFArrayContainsValue ( (__bridge CFArrayRef)numbers, 
                                    CFRangeMake(0, numbers.count), 
                                    (CFNumberRef)value );

Works like a charm and is really fast!

Tieme
  • 62,602
  • 20
  • 102
  • 156
12
    NSPredicate *valuePredicate=[NSPredicate predicateWithFormat:@"self.intValue == %d",[myValueNumber intValue]];

    if ([[numbersArray filteredArrayUsingPredicate:valuePredicate] count]!=0) {   
        // FOUND
    }

    else  {
       //NOT FOUND
    }
Donnit
  • 1,217
  • 12
  • 19
5

Iterating through the array is the best approach here. This is exactly what the containsObject method is doing under the covers. You could sort the array, but that wouldn't give you very much in terms of efficiency.

If you want to be able to look up values quicker than O(n), NSArray/NSMutableArray is probably not the right data structure for you.

csano
  • 13,266
  • 2
  • 28
  • 45
  • Thanks, what would be a better structure for doing this sort of thing? – Henry Aug 07 '11 at 07:35
  • Hard to say without knowing exactly what you're trying to do. Maybe you should describe your scenario in another SO question? – csano Aug 07 '11 at 07:42
  • 2
    NSArray/NSMutableArray IS the right data structure for fast lookup! Just use CFArrayBSearchValues(…) – bernstein Nov 16 '12 at 11:19
3

a little late, but since the array is already ordered (sorted) you should use CFArrayBSearchValues() which does binary search.

example with numbers:

NSArray *array; // or NSMutableArray
NSNumber *value; // search value
CFArrayBSearchValues((__bridge CFArrayRef)array, CFRangeMake(0, array.count),                   
        (CFNumberRef)value, (CFComparatorFunction)CFNumberCompare, NULL);
Tieme
  • 62,602
  • 20
  • 102
  • 156
bernstein
  • 386
  • 1
  • 10
2

Iterating through NSArray is OK if you don't do it too much. And that's what "containObject" does. But I found that when you need lots and lots of those checks, especially if the arrays are big, it will slow your app...

So if it's a check you need to do often, you can always dictionary instead of array. Where the key will be the NSNumber, and the field will be the number of times it appears in the array. Then, you use "ObjectForKey" to check if the number is in the array, you use "allKeys" to get all the values if needed, etc...

Good luck

Lior Frenkel
  • 806
  • 11
  • 25
1

You can simply check like this:

if ([myArray indexOfObject:@(myNumber)] == NSNotFound) {
    NSLog(@"myArray' contauns 'myNumber");
}

Keep Coding.......... :)

Krishna Raj Salim
  • 7,331
  • 5
  • 34
  • 66