【问题标题】:How retrieve an index of an NSArray using a NSPredicate?如何使用 NSPredicate 检索 NSArray 的索引?
【发布时间】:2026-01-25 23:50:01
【问题描述】:

我会知道如何使用NSPredicate 检索NSArray 的索引?

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

我应该使用哪种方法来通过仅提供NSString 来获取“洛杉矶”的索引?
注意:@"Los An"@"geles" 应该返回相同的索引。

【问题讨论】:

    标签: iphone objective-c ios ipad nsarray


    【解决方案1】:

    使用 NSPredicate 您可以获得包含搜索字符串的字符串数组(似乎没有内置方法可以仅获取元素索引):

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

    您只能使用indexesOfObjectsPassingTest: 方法获取索引:

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

    如果您只想获取一个包含您的字符串的元素,您可以使用类似的indexOfObjectPassingTest: 方法。

    【讨论】:

    • @wagashi,谢谢,错误的属性名称。有趣的是,您是第一个发现错误的人 - 7 个月后 :)
    • :) 对了,应该是"^BOOL(id obj, NSUInteger idx, BOOL *stop)"
    【解决方案2】:

    你应该可以用积木来做到这一点。下面是一个 sn-p(我手边没有编译器,所以请原谅任何拼写错误):

    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];
                       }];
    

    基本上你可以使用 indexOfObjectPassingTest: 方法。这需要一个块(“^”之后的代码)并返回与您的谓词匹配的第一个对象的索引(如果不存在匹配项,则返回 NSNotFound)。该块遍历数组中的每个对象,直到找到匹配项(此时它返回索引)或未找到匹配项(此时它返回 NSNotFound)。以下是块编程的链接,可以帮助您理解块内的逻辑:

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

    【讨论】:

      【解决方案3】:

      找到了一种替代方法,在搜索更复杂的情况下很有帮助,因为它允许使用谓词查找对象,然后使用对象查找索引:

      -(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];
      }
      

      【讨论】:

        【解决方案4】:

        我会这样做..

        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
        

        【讨论】:

        • 让我做一些 cmets: 1) 如果没有元素匹配字符串,那么你的 foundInIndex 将保持未初始化并且你不能使用它。 2)您可以使用快速枚举或基于块的枚举获得更好的性能 3)在这里使用 -description 方法没有意义 4)请注意您的代码将在包含搜索字符串的数组中找到最后一个元素
        【解决方案5】:

        基于@Louie 的回答,我没有使用 for 循环,而是使用了对我有用的枚举块。

        我这样做了:-

        NSString *stringToCompare = @"xyz";
        
        [myArray enumerateObjectsUsingBlock:^(id *Obj, NSUInteger idx, BOOL * _Nonnull stop) {
         NSString * tryString = [[myArray objectAtIndex:idx] description];
        
            if ([tryString rangeOfString:stringToCompare].location == NSNotFound) {
        
                        // no match found
        
                 } else {
        
                        //match found and perform your operation. In my case i had removed array object at idx
        
                   }
                }];
        

        【讨论】:

        • Vladimir 解决方案在查找索引方面似乎比这更直接。