Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How retrieve an index of an NSArray using a NSPredicate?

I would know how retrieve an index of an NSArray using a NSPredicate ?

NSArray *array = [NSArray arrayWithObjects:
                  @"New-York City",
                  @"Washington DC",
                  @"Los Angeles",
                  @"Detroit",
                  nil];

Which kind of method should I use in order to get the index of "Los Angles" by giving only a NSString?
NB: @"Los An" or @"geles" should return the same index.

like image 907
klefevre Avatar asked Aug 29 '11 14:08

klefevre


4 Answers

Using NSPredicate you can get array of strings that contain your search string (it seems there's no built-in method to get just element indexes):

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", searchString];
NSArray *filteredArray = [array filteredArrayUsingPredicate: predicate];

You can get only indexes using indexesOfObjectsPassingTest: method:

NSIndexSet *indexes = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
   NSString *s = (NSString*)obj;
   NSRange range = [s rangeOfString: searchString];
   return range.location != NSNotFound;
}];

If you want to get just one element containing your string you can use similar indexOfObjectPassingTest: method for that.

like image 114
Vladimir Avatar answered Oct 22 '22 06:10

Vladimir


You should be able to do this with blocks. Below is a snippet (I don't have a compiler handy so pls excuse any typos):

NSArray *array = [NSArray arrayWithObjects:
              @"New-York City",
              @"Washington DC",
              @"Los Angeles",
              @"Detroit",
              nil];
NSString *matchCity = @"Los";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", matchCity];
NSUInteger index = [self.array  indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
                                return [predicate evaluateWithObject:obj];
                   }];

Essentially you can use the indexOfObjectPassingTest: method. This takes a block (code following the "^") and returns the index for the first object that matches your predicate (or NSNotFound if no match exists). The block iterates through each object in the array until either a match is found (at which point it returns the index) or no match is found (at which point it returns NSNotFound). Here is a link to block programming that can help you understand the logic within the block:

https://developer.apple.com/library/ios/featuredarticles/Short_Practical_Guide_Blocks/

like image 36
armohan Avatar answered Oct 22 '22 05:10

armohan


I would do this..

NSString * stringToCompare = @"geles";
int foundInIndex;

for ( int i=0; i<[array count]; i++ ){

    NSString * tryString = [[array objectAtIndex:i] description];

    if ([tryString rangeOfString:stringToCompare].location == NSNotFound) {
        // no match
    } else {
        //match found
        foundInIndex = i;
    }



}// end for loop
like image 1
Louie Avatar answered Oct 22 '22 06:10

Louie


Found an alternative approach helpful where the search is more complex as it allows predicate to be used to find object then object to find index:

-(NSIndexPath*) indexPathForSelectedCountry{
    NSUInteger indexToCountry = 0;
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isoCode = %@",self.selectedCountry.isoCode];
    NSArray * selectedObject = [self.countryList filteredArrayUsingPredicate:predicate];
    if (selectedObject){
        if (self.searchDisplayController.isActive){
            indexToCountry = [self.searchResults indexOfObject:selectedObject[0]];
        }else{
            indexToCountry = [self.countryList indexOfObject:selectedObject[0]];
        }
    }
    return [NSIndexPath indexPathForRow:indexToCountry inSection:0];
}
like image 3
ptc Avatar answered Oct 22 '22 07:10

ptc