I tried with NSRegularExpression
since CoreData & NSPredicate
seems to manage them, but I couldn't have a working solution (maybe linked to my no expertise in Regex, but could be a lead). I tried also with NSCharacterSet
, but it couldn't say it the number of occurrences was correct..
This maybe not the more sexy way to do it, but, here what you could do:
NSString *searchedWord = @"inputString";
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
for (NSUInteger index = 0; index < [evaluatedObject length]; index++)
{
NSString *subString = [evaluatedObject substringWithRange:NSMakeRange(index, 1)];
NSUInteger numberOfOccurrencesInSearchWord = [self occurrencesOfSubString:subString inString:searchedWord];
NSUInteger numberOfOccurrencesInCurrentWord = [self occurrencesOfSubString:subString inString:evaluatedObject];
if (numberOfOccurrencesInCurrentWord > numberOfOccurrencesInSearchWord)
return FALSE;
}
return TRUE;
}];
//Apply this predicate to your fetch
I put occurrencesOfSubString:inString:
in the class, but it could be a Category on NSString
for example. You could also loop with rangeOfString:option:range
if you prefer them to NSRegularExpression
. Source of the code (slightly modified)
-(NSUInteger)occurrencesOfSubString:(NSString *)subString inString:(NSString *)string
{
NSUInteger numberOfMatches = 0;
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:subString
options:NSRegularExpressionCaseInsensitive error:&error];
if (!error)
numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];
return numberOfMatches;
}
Note: To avoid too much loops, you may want to strip the evaluatedObject
in order to not check repeated value.
For example, if evaluatedObject = @"aaa"
, it will look 3 times for "a". So removing duplicated values in it may improve the speed. Here is a solution.
So the code would be in the predicate block:
NSString *evaluatedWithoutRepeat = [evaluatedObject removeDuplicatedCharacters];
for (NSUInteger index = 0; index <= [evaluatedWithoutRepeat length]; index ++)
{
NSString *subString = [evaluatedWithoutRepeat substringWithRange:NSMakeRange:(index,1)];
//The rest would be the same.
}
WorkingTest:
NSArray *testValues = @[@"inputString",
@"input",
@"string",
@"put",
@"strinpg",
@"Stringpg",
@"stringNOTWANTED"];
NSLog(@"AllValues: %@", testValues);
NSLog(@"Test: %@", [testValues filteredArrayUsingPredicate:predicate]);
Output:
> AllValues: (
inputString,
input,
string,
put,
strinpg,
Stringpg,
stringNOTWANTED
)
> Test: (
inputString,
input,
string,
put,
strinpg
)