如何获取 NSString(例如,@"cake"
)在更大的 NSString(例如,)中出现的次数@"Cheesecake, apple cake, and cherry pie"
?
我需要在很多字符串上执行此操作,因此我使用的任何方法都需要相对较快。
谢谢!
如何获取 NSString(例如,@"cake"
)在更大的 NSString(例如,)中出现的次数@"Cheesecake, apple cake, and cherry pie"
?
我需要在很多字符串上执行此操作,因此我使用的任何方法都需要相对较快。
谢谢!
这未经测试,但应该是一个好的开始。
NSUInteger count = 0, length = [str length];
NSRange range = NSMakeRange(0, length);
while(range.location != NSNotFound)
{
range = [str rangeOfString: @"cake" options:0 range:range];
if(range.location != NSNotFound)
{
range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
count++;
}
}
像下面这样的正则表达式应该可以在没有循环交互的情况下完成这项工作......
已编辑
NSString *string = @"Lots of cakes, with a piece of cake.";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"cake" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];
NSLog(@"Found %i",numberOfMatches);
仅适用于 iOS 4.x 及更高版本。
正在寻找比我更好的方法,但这是另一个例子:
NSString *find = @"cake";
NSString *text = @"Cheesecake, apple cake, and cherry pie";
NSInteger strCount = [text length] - [[text stringByReplacingOccurrencesOfString:find withString:@""] length];
strCount /= [find length];
我想知道哪个更有效。
为了更好地使用,我创建了一个NSString
类别:
// NSString+CountString.m
@interface NSString (CountString)
- (NSInteger)countOccurencesOfString:(NSString*)searchString;
@end
@implementation NSString (CountString)
- (NSInteger)countOccurencesOfString:(NSString*)searchString {
NSInteger strCount = [self length] - [[self stringByReplacingOccurrencesOfString:searchString withString:@""] length];
return strCount / [searchString length];
}
@end
只需通过以下方式调用它:
[text countOccurencesOfString:find];
可选:您可以通过定义将其修改为不区分大小写搜索options:
有几种方法可以做到。您可以迭代调用rangeOfString:options:range:
,或者您可以执行以下操作:
NSArray * portions = [aString componentsSeparatedByString:@"cake"];
NSUInteger cakeCount = [portions count] - 1;
编辑我再次考虑这个问题,我写了一个线性时间算法来进行搜索(与干草堆字符串的长度成线性关系):
+ (NSUInteger) numberOfOccurrencesOfString:(NSString *)needle inString:(NSString *)haystack {
const char * rawNeedle = [needle UTF8String];
NSUInteger needleLength = strlen(rawNeedle);
const char * rawHaystack = [haystack UTF8String];
NSUInteger haystackLength = strlen(rawHaystack);
NSUInteger needleCount = 0;
NSUInteger needleIndex = 0;
for (NSUInteger index = 0; index < haystackLength; ++index) {
const char thisCharacter = rawHaystack[index];
if (thisCharacter != rawNeedle[needleIndex]) {
needleIndex = 0; //they don't match; reset the needle index
}
//resetting the needle might be the beginning of another match
if (thisCharacter == rawNeedle[needleIndex]) {
needleIndex++; //char match
if (needleIndex >= needleLength) {
needleCount++; //we completed finding the needle
needleIndex = 0;
}
}
}
return needleCount;
}
打字速度更快,但效率可能较低的解决方案。
- (int)numberOfOccurencesOfSubstring:(NSString *)substring inString:(NSString*)string
{
NSArray *components = [string componentsSeparatedByString:substring];
return components.count-1; // Two substring will create 3 separated strings in the array.
}
这是一个作为扩展的版本NSString
(与 Matthew Flaschen 的回答相同):
@interface NSString (my_substr_search)
- (unsigned) countOccurencesOf: (NSString *)subString;
@end
@implementation NSString (my_substring_search)
- (unsigned) countOccurencesOf: (NSString *)subString {
unsigned count = 0;
unsigned myLength = [self length];
NSRange uncheckedRange = NSMakeRange(0, myLength);
for(;;) {
NSRange foundAtRange = [self rangeOfString:subString
options:0
range:uncheckedRange];
if (foundAtRange.location == NSNotFound) return count;
unsigned newLocation = NSMaxRange(foundAtRange);
uncheckedRange = NSMakeRange(newLocation, myLength-newLocation);
count++;
}
}
@end
<somewhere> {
NSString *haystack = @"Cheesecake, apple cake, and cherry pie";
NSString *needle = @"cake";
unsigned count = [haystack countOccurencesOf: needle];
NSLog(@"found %u time%@", count, count == 1 ? @"" : @"s");
}
If you want to count words, not just substrings, then use CFStringTokenizer.
这是另一个版本作为 NSString 上的一个类别:
-(NSUInteger) countOccurrencesOfSubstring:(NSString *) substring {
if ([self length] == 0 || [substring length] == 0)
return 0;
NSInteger result = -1;
NSRange range = NSMakeRange(0, 0);
do {
++result;
range = NSMakeRange(range.location + range.length,
self.length - (range.location + range.length));
range = [self rangeOfString:substring options:0 range:range];
} while (range.location != NSNotFound);
return result;
}
快速的解决方案是:
var numberOfSubstringAppearance = 0
let length = count(text)
var range: Range? = Range(start: text.startIndex, end: advance(text.startIndex, length))
while range != nil {
range = text.rangeOfString(substring, options: NSStringCompareOptions.allZeros, range: range, locale: nil)
if let rangeUnwrapped = range {
let remainingLength = length - distance(text.startIndex, rangeUnwrapped.endIndex)
range = Range(start: rangeUnwrapped.endIndex, end: advance(rangeUnwrapped.endIndex, remainingLength))
numberOfSubstringAppearance++
}
}
Matthew Flaschen 的回答对我来说是一个好的开始。这是我最终以方法的形式使用的。我对循环采取了稍微不同的方法。这已通过传递给 stringToCount 和 text 的空字符串以及 stringToCount 作为文本中的第一个和/或最后一个字符进行测试。
我经常使用这种方法来计算传递文本中的段落(即 stringToCount = @"\r")。
希望这对某人有用。
- (int)countString:(NSString *)stringToCount inText:(NSString *)text{
int foundCount=0;
NSRange range = NSMakeRange(0, text.length);
range = [text rangeOfString:stringToCount options:NSCaseInsensitiveSearch range:range locale:nil];
while (range.location != NSNotFound) {
foundCount++;
range = NSMakeRange(range.location+range.length, text.length-(range.location+range.length));
range = [text rangeOfString:stringToCount options:NSCaseInsensitiveSearch range:range locale:nil];
}
return foundCount;
}
假设方法位于名为 myHelperClass 的类中的示例调用...
int foundCount = [myHelperClass countString:@"n" inText:@"Now is the time for all good men to come to the aid of their country"];
for(int i =0;i<htmlsource1.length-search.length;i++){
range = NSMakeRange(i,search.length);
checker = [htmlsource1 substringWithRange:range];
if ([search isEqualToString:checker]) {
count++;
}
}
-(IBAction)search:(id)sender{
int maincount = 0;
for (int i=0; i<[self.txtfmainStr.text length]; i++) {
char c =[self.substr.text characterAtIndex:0];
char cMain =[self.txtfmainStr.text characterAtIndex:i];
if (c == cMain) {
int k=i;
int count=0;
for (int j = 0; j<[self.substr.text length]; j++) {
if (k ==[self.txtfmainStr.text length]) {
break;
}
if ([self.txtfmainStr.text characterAtIndex:k]==[self.substr.text characterAtIndex:j]) {
count++;
}
if (count==[self.substr.text length]) {
maincount++;
}
k++;
}
}
NSLog(@"%d",maincount);
}
}
没有内置方法。我建议返回一个 c 字符串并使用通用的 c 字符串样式算法进行子字符串计数......如果你真的需要这个速度很快。
如果您想继续使用 Objective C,此链接可能会有所帮助。它描述了 NSString 的基本子字符串搜索。如果您使用范围、调整和计数,那么您将拥有一个“纯”的 Objective C 解决方案……尽管速度很慢。