6

Is there a way, in Objective-C/Cocoa, to convert spelled out words to an NSNumber or equivalent in multiple languages?

For example:

convert three to 3 or convert ocho to 8 (Spanish).

Also slightly different, but 3 1/2 to 3.5

I could write my own code to do this, but I was hoping there was a built-in way to do this. Getting the translations of every number in several languages is something I'd like to avoid.

edc1591
  • 10,146
  • 6
  • 40
  • 63
  • 3
    Consider searching the documentation for "natural language" and "NSNumberFormatter" – Joshua Nozzi Mar 28 '13 at 19:57
  • @JoshuaNozzi From what I've found, `NSNumberFormatter` can only do the reverse of this. – edc1591 Mar 28 '13 at 20:03
  • You can create an NSDictionnary that would have the value 1 for the key "one", 2 for "two" and so on. But you have to write each number one after another - not quite practical. – Moray Mar 28 '13 at 20:04
  • Huh? I may be misunderstanding you but I thought you wanted "three" to be converted to an NSNumber instance with the value of "3". But I was wrong anyway: this only works for **NSDateFormatter**. Hence, "tomorrow" would return an NSDate object with "tomorrow's" date relative to [NSDate date]. – Joshua Nozzi Mar 28 '13 at 20:07
  • The above said, what you're asking for is REALLY complicated for even one language, much less multiple. Consider lots of nasty-looking RegEx. – Joshua Nozzi Mar 28 '13 at 20:09
  • @JoshuaNozzi No, you were right. That is what I want to do. So I guess localizing every single word in the range I need would be the only way? – edc1591 Mar 28 '13 at 20:12
  • 1
    You will likely find [ParseKit](http://parsekit.com/) helpful in implementing this. – jscs Mar 28 '13 at 20:19
  • It'd be a more direct way given the current tool set, but I don't know about "the only". – Joshua Nozzi Mar 28 '13 at 22:34

2 Answers2

13

NSNumberFormatter can convert from text to numbers:

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterSpellOutStyle;

NSLog(@"%@", [formatter numberFromString:@"thirty-four"]);
NSLog(@"%@", [formatter numberFromString:@"three point five"]);

formatter.locale = [[NSLocale alloc]initWithLocaleIdentifier:[NSLocale localeIdentifierFromComponents:@{NSLocaleLanguageCode: @"es"}]];

NSLog(@"%@", [formatter numberFromString:@"ocho"]);

There are serious limitations as to what it can handle (it doesn't auto detect languages, if you deviate from the expected format (e.g. "thirty four" instead of "thirty-four"), fractions, etc.), but for the narrow domain, it appears to do the job.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
2

NSLinguisticTagger will flag numbers for you in multiple languages.

NSArray * texts = @[@"It's 3 degrees outside", @"Ocho tacos", @"What is 3 1/2?", @"ocho"];
for (NSString * text in texts)
{
    NSLinguisticTaggerOptions options = NSLinguisticTaggerOmitWhitespace | NSLinguisticTaggerJoinNames;
    NSArray * tagSchemes = [NSLinguisticTagger availableTagSchemesForLanguage:@"en"];
    tagSchemes = [tagSchemes arrayByAddingObjectsFromArray:[NSLinguisticTagger availableTagSchemesForLanguage:@"es"]];

    NSLinguisticTagger * tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:tagSchemes
                                                                                 options:options];
    [tagger setString:text];

    [tagger enumerateTagsInRange:NSMakeRange(0, [text length])
                          scheme:NSLinguisticTagSchemeNameTypeOrLexicalClass
                         options:options
                      usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop)
        {
            NSString *token = [text substringWithRange:tokenRange];
            NSLog(@"%@: %@", token, tag);
        }];
}

This does leave you with the task of identifying how and when to do things like fraction resolution.

Fruity Geek
  • 7,351
  • 1
  • 32
  • 41