Ashok
Ashok

Reputation: 5655

Best way for getting the indexes of matched objects in NSArray in iOS?

I have the following two arrays.

 NSArray *array1=[[NSArray alloc]initWithObjects:@"ABC",@"DEF", nil];
 NSArray *array2=[[NSArray alloc]initWithObjects:@"ABC",@"123",@"DEF",@"DEF", nil];

Now i have to search each array1's object and in array2 and need to get the matched indexes. And my application contains more than one thousand objects in array2.

Please suggest the best possible way other than putting second for loop in first for loop

for (int i=0; i<array1.count; i++)
{
//Need to search the [array1 objectAtIndex:i] string in array2 and need to get the matched indexes into an array in best optimised way here.

    NSMutableArray *matchedIndexesArray=[[NSMutableArray alloc]init];
    NSString *stringToSearch=[array1 objectAtIndex:i];

    //here i can put another array like below to get the matched indexes..but is there any optimized way other than this for loop here? or is there any simple inbuilt method to get the matched objects into an array here.
    for (int j=0; j<array2.count; j++)
    {
        if ([stringToSearch isEqualToString:[array2 objectAtIndex:j]])
        {
            [matchedIndexesArray addObject:[NSString stringWithFormat:@"%d",j]];
        }
    }

    NSLog(@"matchedIndexesArray-->%@<--",matchedIndexesArray);
    //I will use this matchedIndexesArray here further processing...
    //
    //
    //
    //Large Code Here
    //
    //
    //

}

Upvotes: 3

Views: 5304

Answers (3)

James Webster
James Webster

Reputation: 32076

NSArray *a = @[@"123", @"456", @"ABC", @"DEF"];
NSArray *b = @[@"123", @"ABC", @"---"];

NSIndexSet *indexes = [a indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)
{
    return [b containsObject:obj]
}];

NSLog(@"%@", indexes);

Upvotes: 4

Martin R
Martin R

Reputation: 540145

According to the NSSet documentation, membership testing is faster for sets than for arrays. Therefore it makes sense to convert array1 to a set first:

NSSet *set1 = [NSSet setWithArray:array1];

and then test each object of array2 for membership in the set. This can be conveniently done as

NSIndexSet *matchingIndexes = [array2 indexesOfObjectsPassingTest:^BOOL(NSString *obj, NSUInteger idx, BOOL *stop) {
    return [set1 containsObject:obj];
}];

Show all matching indexes:

[matchingIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
    NSLog(@"%ld", (long)idx);
}];
// Output: 0, 2, 3

UPDATE: (after question edit) No, there is no method to fill an NSArray with the indices of matching objects. But there is a method to fill an NSIndexSet. NSIndexSet is a special collection to store indices into some other data structure, such as an array. Then your code would look like

for (NSString *stringToSearch in array1) {
    NSIndexSet *matchingIndexes = [array2 indexesOfObjectsPassingTest:^BOOL(NSString *obj, NSUInteger idx, BOOL *stop) {
        return [stringToSearch isEqualToString:obj];
    }];

    NSLog(@"matchingIndexes: %@", matchingIndexes);

    // Work with matchingIndex, for example enumerate all indices:
    [matchingIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        NSLog(@"%ld", (long)idx);
    }];
}

But I do not know if it makes much difference in performance.

Upvotes: 11

Kumar KL
Kumar KL

Reputation: 15335

NSArray *array1=[[NSArray alloc]initWithObjects:@"ABC",@"DEF", nil];
    NSArray *array2=[[NSArray alloc]initWithObjects:@"ABC",@"123",@"DEF",@"DEF", nil];


    for (int i=0; i<array1.count; i++){
        for (int j=0; j<array2.count; j++) {
            if ([[array1 objectAtIndex:i] isEqualToString: [array2 objectAtIndex:j]]) {
                NSLog(@"Matched Indexes %d %@", i, [array1 objectAtIndex:i] );
            }
        }
       }

Upvotes: 0

Related Questions