Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the first N words from a NSString in Objective-C?

What's the simplest way, given a string:

NSString *str = @"Some really really long string is here and I just want the first 10 words, for example";

to result in an NSString with the first N (e.g., 10) words?

EDIT: I'd also like to make sure it doesn't fail if the str is shorter than N.

like image 325
philfreo Avatar asked Nov 18 '09 00:11

philfreo


4 Answers

If the words are space-separated:

NSInteger nWords = 10;
NSRange wordRange = NSMakeRange(0, nWords);
NSArray *firstWords = [[str componentsSeparatedByString:@" "] subarrayWithRange:wordRange];

if you want to break on all whitespace:

NSCharacterSet *delimiterCharacterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSArray *firstWords = [[str componentsSeparatedByCharactersInSet:delimiterCharacterSet] subarrayWithRange:wordRange];

Then,

NSString *result = [firstWords componentsJoinedByString:@" "];
like image 121
Barry Wark Avatar answered Nov 08 '22 05:11

Barry Wark


While Barry Wark's code works well for English, it is not the preferred way to detect word breaks. Many languages, such as Chinese and Japanese, do not separate words using spaces. And German, for example, has many compounds that are difficult to separate correctly.

What you want to use is CFStringTokenizer:

CFStringRef string; // Get string from somewhere
CFLocaleRef locale = CFLocaleCopyCurrent();

CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, string, CFRangeMake(0, CFStringGetLength(string)), kCFStringTokenizerUnitWord, locale);

CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone;
unsigned tokensFound = 0, desiredTokens = 10; // or the desired number of tokens

while(kCFStringTokenizerTokenNone != (tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) && tokensFound < desiredTokens) {
  CFRange tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer);
  CFStringRef tokenValue = CFStringCreateWithSubstring(kCFAllocatorDefault, string, tokenRange);

  // Do something with the token
  CFShow(tokenValue);

  CFRelease(tokenValue);

  ++tokensFound;
}

// Clean up
CFRelease(tokenizer);
CFRelease(locale);
like image 20
sbooth Avatar answered Nov 08 '22 07:11

sbooth


Based on Barry's answer, I wrote a function for the sake of this page (still giving him credit on SO)

+ (NSString*)firstWords:(NSString*)theStr howMany:(NSInteger)maxWords {

    NSArray *theWords = [theStr componentsSeparatedByString:@" "];
    if ([theWords count] < maxWords) {
        maxWords = [theWords count];
    }
    NSRange wordRange = NSMakeRange(0, maxWords - 1);
    NSArray *firstWords = [theWords subarrayWithRange:wordRange];       
    return [firstWords componentsJoinedByString:@" "];
}
like image 43
philfreo Avatar answered Nov 08 '22 05:11

philfreo


Here's my solution, derived from the answers given here, for my own problem of removing the first word from a string...

NSMutableArray *words = [NSMutableArray arrayWithArray:[lowerString componentsSeparatedByString:@" "]];
[words removeObjectAtIndex:0];
return [words componentsJoinedByString:@" "];
like image 39
Pedro Avatar answered Nov 08 '22 05:11

Pedro