开发者

Better solution for this 2x fast-enumeration?

I'm looping through an array and comparing the objects tag property in this array with the objects in another array.

Here's my code:

NSArray *objectsArray = ...;
NSArray *anotherObjectArray = ...;
NSMutableArray *mutableArray = ...;

for (ObjectA *objectA in objectsArray) {
    for (ObjectZ *objectZ in anotherObje开发者_Python百科ctArray) {
        if ([objectA.tag isEqualToString:objectZ.tag]) {
            [mutableArray addObject:objectA];
        }
    }
}

Is there a better way to do this?

Please note the tag property is not an integer, so have to compare strings.


You can do this by iterating over each array once, rather than nesting:

NSMutableSet *tagSet = [NSMutableSet setWithCapacity:[anotherObjectArray count]];

for(ObjectZ *objectZ in antherObjectArray) {
    [tagSet addObject:objectZ.tag];
}

NSMutableArray *output = [NSMutableArray mutableArray];

for(ObjectA *objectA in objectsArray) {
    if([tagSet containsObject:objectA.tag]) {
        [output addObject:objectA];
    }
}


May be you can use [NSArray filteredArrayUsingPredicate:]; - http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html

But you may have to tweak for property tag yourself.

NSArray *objectsArray = [NSArray arrayWithObjects:@"Miguel", @"Ben", @"Adam", @"Melissa", nil];
NSArray *tagsArray = [NSArray arrayWithObjects:@"Miguel", @"Adam", nil];

NSPredicate *sPredicate = [NSPredicate predicateWithFormat:@"SELF IN %@", tagsArray];
NSArray *results = [objectsArray filteredArrayUsingPredicate:sPredicate];
NSLog(@"Matched %d", [results count]);
for (id a in results) {
    NSLog(@"Object is %@", a);
}

Hope this helps


Well, the simplest change (as there can only be one match per objectA) then you could do a break after your [mutableArray addObject:objectA]. When a match occurs, that would reduce the inner loop by 50%.

More dramatically, if you're doing this a lot and the order of anotherObjectArray doesn't matter, would be to invert your anotherObjectArray data structure and use a dictionary, storing the objects by tag. Then you just iterate over objectA asking if its tag is in the dictionary of ObjectZs.


Thanks for all the answers. While I have accepted the NSMutableSet solution, I actually ended up going with the following, as it turned out it was a tiny bit faster:

NSMutableDictionary *tagDictionary = [NSMutableDictionary dictionaryWithCapacity:[anotherObjectArray count]];
for (ObjectZ *objectZ in anotherObjectArray) {
    [tagDictionary setObject:objectZ.tag forKey:objectZ.tag];
    }
for (ObjectA *objectA in objectsArray) {
    if ([tagDictionary objectForKey:objectA.tag]) {
        [direction addObject:objectA];
    }
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜