Find all locations of substring in NSString (not just first)

后端 未结 6 1813
广开言路
广开言路 2020-11-30 04:12

There is a substring that occurs in a string several times. I use rangeOfString, but it seems that it can only find the first location. How can I find all the l

6条回答
  •  有刺的猬
    2020-11-30 04:28

    This is my solution. Basically, the algorithm traverses the string looking for substring matches and returns those matches in an array.

    Since an NSRange is a struct it cannot be added to the array directly. By using NSValue, I can encode the match first and then add it to the array. To retrieve the range, I then decode the NSValue object to an NSRange.

    #import 
    
    NSRange makeRangeFromIndex(NSUInteger index, NSUInteger length) {
        return NSMakeRange(index, length - index);
    }
    
    NSArray * allLocationsOfStringMatchingSubstring(NSString *text, NSString *pattern) {
        NSMutableArray *matchingRanges = [NSMutableArray new];
        NSUInteger textLength = text.length;
        NSRange match = makeRangeFromIndex(0, textLength);
    
        while(match.location != NSNotFound) {
            match = [text rangeOfString:pattern options:0L range:match];
            if (match.location != NSNotFound) {
                NSValue *value = [NSValue value:&match withObjCType:@encode(NSRange)];
                [matchingRanges addObject:value];
                match = makeRangeFromIndex(match.location + 1, textLength);
            }
        }
    
        return [matchingRanges copy];
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSString *text = @"TATACCATGGGCCATCATCATCATCATCATCATCATCATCATCACAG";
            NSString *pattern = @"CAT";
            NSArray *matches = allLocationsOfStringMatchingSubstring(text, pattern);
    
            NSLog(@"Text: %@", text);
            NSLog(@"Pattern: %@", pattern);
            NSLog(@"Number of matches found: %li", matches.count);
    
            [matches enumerateObjectsUsingBlock:^(NSValue *obj, NSUInteger idx, BOOL *stop) {
                NSRange match;
                [obj getValue:&match];
                NSLog(@"   Match found at index: %li", match.location);
            }];
        }
        return 0;
    }
    

提交回复
热议问题