2011-08-11 3 views
27

文字列に何度か出現する部分文字列がある。私はrangeOfStringを使用していますが、最初の場所しか見つけることができないようです。どのように部分文字列のすべての場所を見つけることができますか?NSStringの部分文字列のすべての場所を見つける(最初だけではない)

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

嘆願のすべての場所を検索SE、私は[NSRegularExpressions] [1] になり –

+1

...あなたの質問をより明確にする[1]:http://stackoverflow.com/questions/4353834/search-through-nsstring-using-正規表現 – EricS

答えて

70

rangeOfString:options:range:を使用して、3番目の引数を最初のオカレンスの範囲外に設定できます。

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

これは、部分文字列の出現が重複しないことを前提としています。一般に、合理的な仮定ではないかもしれない。干し草 "ababab"を考えてみましょう。針「abab」は、位置0および位置2(位置0の針と重なり合っている)に現れる。位置2は、上記アルゴリズムによって無視される。 – kevinlawler

+3

テキスト「+ foundRange.length」をテキスト「+1」に変更すると、適切な方法でアルゴリズムが変更されます。 – kevinlawler

1

にnilを渡す[文字列rangeOfString:サブオプション:ゼロ範囲:探索範囲】例えば、あなたはこのような何かを行うことができます。に警告が表示されます。

このグループから列挙型に入れて警告を取り除くために

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

ここkevinlawlerからの入力にPengOneの答えのスウィフト2.2とGibtang

でバージョンです注:文字列と部分文字列は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

これは私のソリューションです。基本的に、アルゴリズムは部分文字列の一致を探して文字列を走査し、その一致を配列に返します。

NSRangeは構造体であるため、配列に直接追加することはできません。 NSValueを使用すると、にエンコードしてから配列に追加できます。範囲を取得するには、NSValueオブジェクトを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

スウィフト3.0

サブ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; 

そして、この出力 -

enter image description here

関連する問題