开发者

Better alternative for checking existence of NSDictionary's key in NSArray?

I have an NSArray of NSDictionaries. I need to check if there's at least one occurrence of an object for a key of the NSDictionary in the NSArray. I do this by using

int i;
for (i=0;i< [myArray count];i++)
{
    if ([[[myArray objectAtIndex: i] objectForKey: myKey] isEqualToString: myString]) {
        found = YES;
        break;
    } else {
        found = NO开发者_StackOverflow社区;
    }
}

But I have a suspicion that there's a better/faster alternative for it...

Thanks


Yes. Use "fast enumeration", commonly also known as for-in loop:

for (NSDictionary* dict in myArray) {

Also, to compare NSString's, use -isEqualToString:.

   if ([[dict objectForKey: myKey] isEqualToString:myString]) {

That said, there is no algorithmic improvement to this (i.e. this method is already the best.)


This is as fast as you can get it with your current data structures. You're doing an O(1) lookup for each dictionary in the array. If you have a huge number of dictionaries, this might get expensive, so you could consider (depending very much on the semantics of your data) keeping a separate lookaside NSSet that contains the set of string objects comprising all the values in the dictionaries. Then you can check once in that set for existence.

Tell us more about the form of the data for more insight...

Also be careful with the == operator with NSStrings. If you're actually checking to see whether the text of the string is equal, you should use -isEqualToString: instead, as your form will just do a reference comparison.


You should use fast enumeration, which will iterate through the objects using a C array behind the scenes. Right now, you're calling both -objectAtIndex: and -count each time through the loop.

You might also check out NSPredicate if myKey is a string. My gut tells me it would be slower, but you never know if it might benefit from internal optimization for NSDictionary:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ LIKE %@", myKey, myString];
BOOL found = ([[myArray filteredArrayUsingPredicate:predicate] count] > 0);


You could be much more succinct with Key-Value Coding:

[[myArray valueForKey:myKey] containsObject:myString];

It's not necessarily faster (I suspect it will be slower), but speed is not always the primary concern. Whether speed is critical in a particular case is a matter for profiling to decide.


Using == to check string equality might cause unexpected behavior, because you're actually comparing pointers (that can be okay if you're sure that you're dealing with a single string object pointed to by two pointers). isEqualToString: is probably what you want instead.

You can use "fast enumeration" to simplify things slightly:

bool found = NO;

for (NSDictionary *dict in myArray) {
    found = [[dict objectForKey:myKey] isEqualToString:myString];

    if (found)
        break;
}

It's only "faster" in the sense that it's fewer words to write; the execution speed is the same.


After receiving your object, You can check that your received object is "NSArray" or "NSDictionary" or "NSString" etc. You can use following code to verify your object.

if([obj isKindOfClass:[NSArray class]]){
    NSLog(@"IS NSArray");
}
else if([obj isKindOfClass:[NSDictionary class]]){
    NSLog(@"Is NSDictionary");
}
else
{
    NSLog(@"Other");
}


With fast enumeration

BOOL found;

for (NSDictionary *dict in array) {

        if ([[dict objectForKey:@"YOURKEY"] isEqualToString:@"YOURVALUE"]) {
            found = YES;
            break;
        } else {
            found = NO;
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜