xcode 在 NSString 中查找子字符串的所有位置(不仅仅是第一个)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7033574/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find all locations of substring in NSString (not just first)
提问by forest
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 locations of the substring?
有一个子串在一个字符串中出现多次。我用rangeOfString
,但似乎只能找到第一个位置。如何找到子字符串的所有位置?
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);
回答by PengOne
You can use rangeOfString:options:range:
and set the third argument to be beyond the range of the first occurrence. For example, you can do something like this:
您可以使用rangeOfString:options:range:
并将第三个参数设置为超出第一次出现的范围。例如,您可以执行以下操作:
NSRange searchRange = NSMakeRange(0,string.length);
NSRange foundRange;
while (searchRange.location < string.length) {
searchRange.length = string.length-searchRange.location;
foundRange = [string rangeOfString:substring options:0 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;
}
}
回答by Abhishek Jain
Swift 3.0
斯威夫特 3.0
Find all locations of substring i
查找子串的所有位置 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;
And this output-
而这个输出——
回答by titusmagnus
This is my solution. Basically, the algorithm traverses the string looking for substring matches and returns those matches in an array.
这是我的解决方案。基本上,该算法遍历字符串以查找子字符串匹配项并在数组中返回这些匹配项。
Since an NSRangeis a struct it cannot be added to the array directly. By using NSValue, I can encodethe match first and then add it to the array. To retrieve the range, I then decodethe NSValueobject to an NSRange.
由于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;
}
回答by Gibtang
Passing nil to [string rangeOfString:substring options:nil range:searchRange];shows a warning.
将 nil 传递给[string rangeOfString:substring options:nil range:searchRange]; 显示警告。
To get rid of the warning, put in an enum from this group
要摆脱警告,请放入来自该组的枚举
enum {
NSCaseInsensitiveSearch = 1,
NSLiteralSearch = 2,
NSBackwardsSearch = 4,
NSAnchoredSearch = 8,
NSNumericSearch = 64,
NSDiacriticInsensitiveSearch = 128,
NSWidthInsensitiveSearch = 256,
NSForcedOrderingSearch = 512,
NSRegularExpressionSearch = 1024
};
回答by bwait
Here is a version in Swift 2.2 of PengOne's answer with input from kevinlawler and Gibtang
这是 PengOne 答案的 Swift 2.2 版本,其中包含来自 kevinlawler 和 Gibtang 的输入
Note: string and substring are of type NSString
注意:string 和 substring 是 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
}
}