1

How do you remove the first N number of words from an NSString?

For example... "I went to the store to buy milk." I want to remove the first three words to make it...

"the store to buy milk." (notice there's no space before the word 'the' either).

Thanks!

Rohan Agarwal
  • 2,167
  • 1
  • 24
  • 34

4 Answers4

3

This question can be rephrased as "how can I get a substring starting at the 4th word in a string?", which is slightly easier to solve. I'm also assuming here that strings with fewer than 4 words should become empty.

Anyway, the workhorse here is -enumerateSubstringsInRange:options:usingBlock:, which we can use to find the 4th word.

NSString *substringFromFourthWord(NSString *input) {
    __block NSUInteger index = NSNotFound;
    __block NSUInteger count = 0;
    [input enumerateSubstringsInRange:NSMakeRange(0, [input length]) options:(NSStringEnumerationByWords|NSStringEnumerationSubstringNotRequired) usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        if (++count == 4) {
            // found the 4th word
            index = substringRange.location;
            *stop = YES;
        }
    }];
    if (index == NSNotFound) {
        return @"";
    } else {
        return [input substringFromIndex:index];
    }
}

The way this works is we're asking -enumerateSubstrings... to enumerate by words. When we find the 4th word, we save off its starting location and exit the loop. Now that we have the start of the 4th word we can just get the substring from that index. If we didn't get 4 words, we return @"".

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
1

The best answers are here: How to get the first N words from a NSString in Objective-C?

You'll just need to change the range.

Community
  • 1
  • 1
Blake Schwendiman
  • 442
  • 1
  • 4
  • 9
  • That's actually the inverted question. The accepted answer there also isn't locale-aware. It only works for languages that delimit words using spaces. And the second answer a) uses a more complicated API than we can now use in `NSString`, and b) assumes the current locale is the locale of the string, whereas I *believe* the default behavior of `-enumerateSubstrings...` detects the locale from the text. – Lily Ballard Mar 12 '13 at 19:51
1

Solution #1: just do it the way you would do it manually: skip the first n spaces.

NSString *cutToNthWord(NSString *orig, NSInteger idx)
{
    NSRange r = NSMakeRange(0, 0);
    for (NSInteger i = 0; i < idx; i++) {
        r = [orig rangeOfString:@" "
                        options:kNilOptions
                          range:NSMakeRange(NSMaxRange(r), orig.length - NSMaxRange(r))];
    }
    return [orig substringFromIndex:NSMaxRange(r)];
}

Solution #2 (cleaner): split the string at spaces, join the last n - k element of the resulting array, where k is the number of words to skip, n is the total number of words:

NSString *cutToNthWord(NSString *orig, NSInteger idx)
{
    NSArray *comps = [orig componentsSeparatedByString:@" "];
    NSArray *sub = [comps subarrayWithRange:NSMakeRange(idx, comps.count - idx)];
    return [sub componentsJoinedByString:@" "];
}
0

Off the top of my head and not as slick as Kevin Ballard's solution:

NSString *phrase = @"I went to the store to buy milk.";

NSMutableString *words = [[NSMutableString alloc] init];
NSArray *words = [phrase componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

NSMutableIndexSet *indexes = [NSMutableIndexSet indexSetWithIndex:1];
[indexes addIndex:2];
[indexes addIndex:3];
[words removeObjectsAtIndexes:indexes];

NSString *output = [words componentsJoinedByString:@" "];

My code will not work for languages that do not use spaces between words (like Mandarin and some other Far East languages).

Robotic Cat
  • 5,899
  • 4
  • 41
  • 58