Как получить индекс NSArray с использованием NSPredicate?
Я бы знал, как получить индекс NSArray
с помощью NSPredicate
?
NSArray *array = [NSArray arrayWithObjects:
@"New-York City",
@"Washington DC",
@"Los Angeles",
@"Detroit",
nil];
Какой тип метода я должен использовать, чтобы получить индекс "Los Angles", указав только NSString
NB: @"Los An"
или @"geles"
должен вернуть тот же индекс.
Ответы
Ответ 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:
.
Ответ 2
Вы должны иметь возможность делать это с помощью блоков. Ниже приведен фрагмент (у меня нет компилятора, поэтому pls извините за любые опечатки):
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
Ответ 5
Основываясь на ответе @Louie, вместо использования для цикла я использовал блок перечисления, который работал у меня.
Я сделал это: -
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
}
}];