2011-08-11 42 views
27

Có một chuỗi con xuất hiện trong chuỗi nhiều lần. Tôi sử dụng rangeOfString, nhưng có vẻ như nó chỉ có thể tìm thấy vị trí đầu tiên. Làm thế nào tôi có thể tìm thấy tất cả các vị trí của chuỗi con?Tìm tất cả các vị trí của chuỗi con trong NSString (không chỉ đầu tiên)

NSString *subString1 = @"</content>"; 
NSString *subString2 = @"--\n"; 
NSRange range1 = [newresults rangeOfString:subString1]; 
NSRange range2 = [newresults rangeOfString:subString2]; 
int location1 = range1.location; 
int location2 = range2.location; 
NSLog(@"%i",location1); 
NSLog(@"%i",location2); 
+0

lời biện hộ này se làm cho câu hỏi của bạn rõ ràng hơn ... –

+1

tôi sẽ xem xét [NSRegularExpressions] [1] [1]: http://stackoverflow.com/questions/4353834/search-through-nsstring-using- biểu thức chính quy – EricS

Trả lời

70

Bạn có thể sử dụng rangeOfString:options:range: và đặt đối số thứ ba vượt quá phạm vi xảy ra đầu tiên. Ví dụ, bạn có thể làm một cái gì đó như thế này:

NSRange searchRange = NSMakeRange(0,string.length); 
NSRange foundRange; 
while (searchRange.location < string.length) { 
    searchRange.length = string.length-searchRange.location; 
    foundRange = [string rangeOfString:substring options:nil range:searchRange]; 
    if (foundRange.location != NSNotFound) { 
     // found an occurrence of the substring! do stuff here 
     searchRange.location = foundRange.location+foundRange.length; 
    } else { 
     // no more substring to find 
     break; 
    } 
} 
+4

Điều này giả định rằng các lần xuất hiện chuỗi con không trùng lặp, điều này là hợp lý khi xem xét câu hỏi. Nói chung nó có thể không phải là một giả định hợp lý. Hãy xem xét haystack "ababab". Kim "abab" xuất hiện ở vị trí 0 và ở vị trí 2 (chồng kim vào vị trí 0). Vị trí 2 sẽ bị bỏ qua bởi thuật toán trên. – kevinlawler

+3

Thay đổi văn bản "+ foundRange.length" thành văn bản "+1" sửa đổi thuật toán theo cách thích hợp. – kevinlawler

1

Đi qua con số không để [chuỗi rangeOfString: tùy chọn chuỗi con: phạm vi nil: searchRange]; hiển thị cảnh báo.

Để thoát khỏi cảnh báo, đặt trong một enum từ nhóm này

enum { 
    NSCaseInsensitiveSearch = 1, 
    NSLiteralSearch = 2, 
    NSBackwardsSearch = 4, 
    NSAnchoredSearch = 8, 
    NSNumericSearch = 64, 
    NSDiacriticInsensitiveSearch = 128, 
    NSWidthInsensitiveSearch = 256, 
    NSForcedOrderingSearch = 512, 
    NSRegularExpressionSearch = 1024 
}; 

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/index.html#//apple_ref/doc/constant_group/Search_and_Comparison_Options

0

Đây là một phiên bản trong Swift 2.2 của câu trả lời PengOne với đầu vào từ kevinlawler và Gibtang

Lưu ý: chuỗi và chuỗi con thuộc loại NSString

let fullStringLength = (string as String).characters.count 
var searchRange = NSMakeRange(0, fullStringLength) 
while searchRange.location < fullStringLength { 
    searchRange.length = fullStringLength - searchRange.location 
    let foundRange = string.rangeOfString(substring as String, options: .CaseInsensitiveSearch, range: searchRange) 
    if foundRange.location != NSNotFound { 
     // found an occurrence of the substring! do stuff here 
     searchRange.location = foundRange.location + 1 
    } else { 
     // no more strings to find 
     break 
    } 
} 
2

Đây là giải pháp của tôi. Về cơ bản, thuật toán đi qua chuỗi tìm kiếm các chuỗi con phù hợp và trả về các kết quả phù hợp đó trong một mảng.

Vì một số NSRange là cấu trúc, nó không thể được thêm trực tiếp vào mảng. Bằng cách sử dụng NSValue, tôi có thể mã hóa khớp đầu tiên và sau đó thêm nó vào mảng. Để truy xuất phạm vi, tôi sau đó giải mã NSValue đối tượng vào một NSRange.

#import <Foundation/Foundation.h> 

NSRange makeRangeFromIndex(NSUInteger index, NSUInteger length) { 
    return NSMakeRange(index, length - index); 
} 

NSArray<NSValue *> * 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<NSValue *> *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; 
} 
0

Swift 3,0

Tìm tất cả các vị trí của chuỗi con i

let text = "This is the text and i want to replace something" 
let mutableAttributedString = NSMutableAttributedString(string: text) 

var searchRange = NSRange(location: 0, length: text.characters.count) 
var foundRange = NSRange() 
while searchRange.location < text.characters.count { 
    searchRange.length = text.characters.count - searchRange.location 
    foundRange = (text as NSString).range(of: "i", options: NSString.CompareOptions.caseInsensitive, range: searchRange) 
    if foundRange.location != NSNotFound { 
     // found an occurrence of the substring! do stuff here 
     searchRange.location = foundRange.location + foundRange.length 
     mutableAttributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: foundRange) 
    } 
    else { 
     // no more substring to find 
     break 
    } 
} 

//Apply 
textLabel.attributedText = mutableAttributedString; 

Và output-

enter image description here

Các vấn đề liên quan