2

I'm pretty new to using regex in iOS, and I'm experimenting with it. I'm struggling to find a solution to the problem I have. I apologize in advance if this has been answered before or I'm just missing something really obvious and/or using the wrong tool to accomplish my goal.

I have a string that the user will enter in a textfield. How do I then change that to correct a spelling of a word that is contained inside the string?

NSString *userstring = @"Jon Travalta";
NSError *error = NULL;
NSString *modstring = @"";

NSRegularExpression *regex = [[NSRegularExpression alloc]init];
regex = [NSRegularExpression regularExpressionWithPattern:@"(Jon|Johnathan|Jonathen|John)\\s(Travalta|Travalte|Travelta|Travolta)" options:NSRegularExpressionCaseInsensitive error:&error];

modstring = [regex stringByReplacingMatchesInString:userstring options:0 range:NSMakeRange(0,[userstring length]) withTemplate:@"John Travolta"];

That works and corrects the string fine, but let's say the string is something else. I want to keep that regex active to check the string if it contains any of those elements to correct it.

So let's say the string is set, before the above check, to "Anthony Hopkin". I would then also use another regexwithpattern to check the string to correct that one with the correct spelling of the name.

regex = [NSRegularExpression regularExpressionWithPattern:@"(Anthony|Antony|Tony|)\\s(Hopkin|Hapkin|Hopkins)" options:NSRegularExpressionCaseInsensitive error:&error];

modstring = [regex stringByReplacingMatchesInString:userstring options:0 range:NSMakeRange(0,[userstring length]) withTemplate:@"Anthony Hopkins"];

This will replace the string with Anthony Hopkins, even if it's the first string.

If I do a different alloc of NSRegularExpression and different stringByReplacingMatchesInString, it just doesn't do anything and the string stays what it was to begin with.

Niels Castle
  • 8,039
  • 35
  • 56
Ac128
  • 33
  • 3
  • Are you asking if a single expression can match all possible names. The answer is that it can, by combining them into 1. However, the replacement would have to know which one matched. This would require a dynamic string as opposed to a static string. –  Dec 16 '15 at 17:45
  • @sln i agree a single expression is probably the way i will go with it, But how would i use a dynamic string to check which one matched to choose which replacement would be called. Could you give me an example please? i would be very grateful – Ac128 Dec 17 '15 at 11:08
  • the easiest way of eliminating typos is generating _soundex_ values, it might work in your case as well on. – holex Dec 17 '15 at 12:13
  • Not sure I understand your issue. Can you give the actual code you use when you have the issue, what the output is, and what you expect it to be? – jcaron Dec 17 '15 at 12:17
  • @jcaron so if i do this: regexVal = [NSRegularExpression regularExpressionWithPattern:@"(Jon|Johnathan|Jonathan|John)\\s(Travalta|Travalte|Travolta) | (Antony|Anthony|Tony)\\s(Hopkin|Hapkin|Hopkins)" options:NSRegularExpressionCaseInsensitive error:&error]; then i want to replace any of the spelling mistake of the first expression to @"Jon Travolta" and the second one to @"Anthony Hopkins" though if i use StringByReplacingMatchesInString it'll replace both with whatever i set the last Template to. so it will even replace John Travalta with Anthony Hopkins – Ac128 Dec 17 '15 at 13:48
  • Don't add lengthy code in comments, update your question. Obviously, if you use a single regex that matches both, it will replace both by the same text. You need to create one regex, use it to replace, create another regex, use it to replace, etc. This may be done manually, or using a loop with input from a dictionary or array. – jcaron Dec 17 '15 at 15:48

2 Answers2

2

Regular expressions are not the right tool for spell checking.

In your question you want to make multiple replacements based on regular expressions. For clarity I'd just iterate though your list of possible corrections applying them one at a time.

-(NSString*) naiiveSpellCheckString:(NSString*) s {

  NSDictionary* corrections = @{
                                @"Travolta": @"Travalta|Travalte|Travelta|Travolta",
                                @"John": @"Jon|Johnathan|Jonathen",
                                @"Anthony":@"Anthoni|Antony|Tony",
                                @"Hopkins": @"Hopkin|Hapkin",
                                };

  for (NSString* key in corrections.keyEnumerator) {

      NSError* error;
      NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[corrections objectForKey:key]
                                    options:NSRegularExpressionCaseInsensitive
                                    error:&error];

      NSAssert1(!error, @"Error parsing regex %@", [corrections objectForKey:key]);

      s = [regex stringByReplacingMatchesInString:s
                                          options:0
                                            range:NSMakeRange(0, s.length) withTemplate:key];

  }

  return s;
}
Niels Castle
  • 8,039
  • 35
  • 56
0

I ran into the same thing and I built a method that will build the expression for me from an array of stings.

NSArray* itemsArray = [@“Jon”, @“Johnathan”, @“Johnathen”, @“John”];

NSMutableString* builtString = @“”;

for (NSString* aItem in itemsArray) {
    NSString* formatString;
    if (![builtSting hasSuffix:@“| “] ) {
        formatString = [NSSting stringWithFormat:@“%@”, aItem];
    }
    else {
        formatString = [NSSting stringWithFormat:@“ | %@”, aItem];
    }
[builtSting stringByAppendingString:formatString];
}

———————————-

add any prefixes or suffixes to complete the expression

repeat for last names group

combine the groups and add any additional regex prefixes Or suffixes.

It may be easier to just execute the search on each name, rather than combining a super large multi first names / last names one. (And easier to debug)

Till Kolditz
  • 554
  • 5
  • 13