Retrieving a dictionary substring from NSString at a given index

I want to pull a substring from an NSString at a given index. Example:

NSString = @"Hello, welcome to the jungle";
int index = 9;

The pointer point β€œ9” is in the middle of the word β€œwelcome,” and I would like to be able to extract the word β€œwelcome” as a substring. Can someone tell me how I will achieve this? With regex?

+5
source share
2 answers

Here's the solution as a category on NSString:

- (NSString *) wordAtIndex:(NSInteger) index {
    __block NSString *result = nil;
    [self enumerateSubstringsInRange:NSMakeRange(0, self.length)
                             options:NSStringEnumerationByWords
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                              if (NSLocationInRange(index, enclosingRange)) {
                                  result = substring;
                                  *stop = YES;
                              }
                          }];
    return result;
}

And one more, which is more difficult, but allows you to precisely specify the words you need:

- (NSString *) wordAtIndex:(NSInteger) index {
    if (index < 0 || index >= self.length)
        [NSException raise:NSInvalidArgumentException
                    format:@"Index out of range"];

    // This definition considers all punctuation as word characters, but you
    // can define the set exactly how you like
    NSCharacterSet *wordCharacterSet =
    [[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet];

    // 1. If [self characterAtIndex:index] is not a word character, find
    // the previous word. If there is no previous word, find the next word.
    // If there are no words at all, return nil.
    NSInteger adjustedIndex = index;
    while (adjustedIndex < self.length &&
           ![wordCharacterSet characterIsMember:
            [self characterAtIndex:adjustedIndex]])
        ++adjustedIndex;
    if (adjustedIndex == self.length) {
        do
            --adjustedIndex;
        while (adjustedIndex >= 0 &&
               ![wordCharacterSet characterIsMember:
                [self characterAtIndex:adjustedIndex]]);
        if (adjustedIndex == -1)
            return nil;
    }

    // 2. Starting at adjustedIndex which is a word character, find the
    // beginning and end of the word
    NSInteger beforeBeginning = adjustedIndex;
    while (beforeBeginning >= 0 &&
           [wordCharacterSet characterIsMember:
            [self characterAtIndex:beforeBeginning]])
        --beforeBeginning;

    NSInteger afterEnd = adjustedIndex;
    while (afterEnd < self.length &&
           [wordCharacterSet characterIsMember:
            [self characterAtIndex:afterEnd]])
        ++afterEnd;

    NSRange range = NSMakeRange(beforeBeginning + 1,
                                afterEnd - beforeBeginning - 1);
    return [self substringWithRange:range];
}

The second version is also more effective with long lines if the words are short.

+9
source

Here is a pretty hacky way to do this, but it will work:

NSString has a method:

- (NSArray *)componentsSeparatedByString:(NSString *)separator;

so you can:

NSString *myString = @"Blah blah blah";
NSString *output = @"";
int index = 9;
NSArray* myArray = [myString componentsSeparatedByString:@" "]; // <-- note the space in the parenthesis

for(NSString *str in myArray) {
    if(index > [str length]) index -= [str length] + 1; // don't forget the space that *was* there
    else output = str;
}
+1
source

All Articles