Reputation: 217
I'm making an iOS app and I need to figure out if an NSString
contains any of the NSStrings
in an NSArray
.
Upvotes: 18
Views: 20704
Reputation: 890
It may be a silly optimization for your use case, but depending on how large the array is that you are iterating, it may be helpful/more performant to use NSArray's
indexOfObjectWithOptions:passingTest:
method.
With this method you pass some options and a block that contains your test. Passing the NSEnumerationConcurrent
option will allow the evaluation of your block to occur on multiple threads concurrently and potentially speed things up. I reused invariant's test, but in a slightly different way. The block functionally returns a BOOL similar to the "found" variable in invariant's implementation. The "*stop = YES;" line indicates that iterating should stop.
See the NSArray reference documentation for more info. Reference
NSArray *arrayOfStrings = ...;
NSString *stringToSearchWithin = @"...";
NSUInteger index = [arrayOfStrings indexOfObjectWithOptions:NSEnumerationConcurrent
passingTest:^(id obj, NSUInteger idx, BOOL *stop)
{
NSString *s = (NSString *)obj;
if ([stringToSearchWithin rangeOfString:s].location != NSNotFound) {
*stop = YES;
return YES;
}
return NO;
}];
if (arrayOfStrings == nil || index == NSNotFound)
{
NSLog(@"The string does not contain any of the strings from the arrayOfStrings");
return;
}
NSLog(@"The string contains '%@' from the arrayOfStrings", [arrayOfStrings objectAtIndex:index]);
Upvotes: 14
Reputation: 7238
As with the release of iOS8, Apple added a new method to NSString
called localizedCaseInsensitiveContainsString
. This will exactly do what you want way easier:
BOOL found = NO;
NSString *string = @"ToSearchFor";
for (NSString *s in arrayOfStrings){
if ([string localizedCaseInsensitiveContainsString:s]) {
found = YES;
break;
}
}
Upvotes: 0
Reputation: 101
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", theArray];
BOOL result = [predicate evaluateWithObject:theString];
Upvotes: 4
Reputation: 38667
Very small security improvement on Adam's answer: there is a big issue with "objectAtIndex:" because it is totally not thread-safe and will make your app crash much too often. So I do:
NSArray *arrayOfStrings = ...;
NSString *stringToSearchWithin = ...";
__block NSString *result = nil;
[arrayOfStrings indexOfObjectWithOptions:NSEnumerationConcurrent
passingTest:^(NSString *obj, NSUInteger idx, BOOL *stop)
{
if ([stringToSearchWithin rangeOfString:obj].location != NSNotFound)
{
result = obj;
*stop = YES;
//return YES;
}
return NO;
}];
if (!result)
NSLog(@"The string does not contain any of the strings from the arrayOfStrings");
else
NSLog(@"The string contains '%@' from the arrayOfStrings", result);
Upvotes: 4
Reputation: 15857
BOOL found=NO;
for (NSString *s in arrayOfStrings)
{
if ([stringToSearchWithin rangeOfString:s].location != NSNotFound) {
found = YES;
break;
}
}
Upvotes: 36