Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NSString中字符的出现次数_String_Cocoa_Cocoa Touch_Nsstring_Character - Fatal编程技术网

NSString中字符的出现次数

NSString中字符的出现次数,string,cocoa,cocoa-touch,nsstring,character,String,Cocoa,Cocoa Touch,Nsstring,Character,我有一个NSString或NSMutableString,希望获得特定字符的出现次数 我需要对相当多的字符(本例中为大写的英语字符)执行此操作,因此它的速度非常快。我可能会使用 NSString rangeOfCharacterFromSet: 或 rangeOfCharacterFromSet:选项:范围: 其中,set是您正在搜索的字符集。它返回与集合匹配的第一个字符的位置。保留数组或字典并增加字符的计数,然后重复。将返回在NSMutableString中替换的字符数 [string rep

我有一个
NSString
NSMutableString
,希望获得特定字符的出现次数

我需要对相当多的字符(本例中为大写的英语字符)执行此操作,因此它的速度非常快。

我可能会使用

NSString rangeOfCharacterFromSet:

rangeOfCharacterFromSet:选项:范围:

其中,set是您正在搜索的字符集。它返回与集合匹配的第一个字符的位置。保留数组或字典并增加字符的计数,然后重复。

将返回在
NSMutableString
中替换的字符数

[string replaceOccurrencesOfString:@"A" 
                        withString:@"B" 
                           options:NSLiteralSearch 
                             range:NSMakeRange(0, [receiver length])];

无论何时在
NSString
中查找内容,请先尝试使用
NSScanner

NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *scanner = [NSScanner scannerWithString:yourString];

NSCharacterSet *charactersToCount = [NSCharacterSet characterSetWithCharactersInString:@"C"]; // For example
NSString *charactersFromString;

if (!([scanner scanCharactersFromSet:charactersToCount 
                          intoString:&charactersFromString])) {
    // No characters found
    NSLog(@"No characters found");
}

// should return 2 for this
NSInteger characterCount = [charactersFromString length];

扫描仪的例子在iPhone上崩溃了。我找到了这个解决方案:

NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *mainScanner = [NSScanner scannerWithString:yourString];
NSString *temp;
NSInteger numberOfChar=0;
while(![mainScanner isAtEnd])
{
   [mainScanner scanUpToString:@"C" intoString:&temp];
   numberOfChar++;
   [mainScanner scanString:@"C" intoString:nil];
}

它对我起作用了,没有崩溃。希望能有帮助

您的解决方案对我不起作用,我在循环中添加了一个条件,仅当mainScanner到达字符串末尾时,才递增numberOfChar:

NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *mainScanner = [NSScanner scannerWithString:yourString];
NSString *temp;
NSInteger numberOfChar=0;
while(![mainScanner isAtEnd])
{
   [mainScanner scanUpToString:@"C" intoString:&temp];
   if(![mainScanner isAtEnd]) {
      numberOfChar++;
      [mainScanner scanString:@"C" intoString:nil];
   }
}

请注意,这是一个快速解决方案,我没有时间制定一个优雅的解决方案…

您可以在一行中完成。例如,这会计算空间数:

NSUInteger numberOfOccurrences = [[yourString componentsSeparatedByString:@" "] count] - 1;

在NSString上尝试此类别:

@implementation NSString (OccurrenceCount)

- (NSUInteger)occurrenceCountOfCharacter:(UniChar)character
{
    CFStringRef selfAsCFStr = (__bridge CFStringRef)self;

    CFStringInlineBuffer inlineBuffer;
    CFIndex length = CFStringGetLength(selfAsCFStr);
    CFStringInitInlineBuffer(selfAsCFStr, &inlineBuffer, CFRangeMake(0, length));

    NSUInteger counter = 0;

    for (CFIndex i = 0; i < length; i++) {
        UniChar c = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, i);
        if (c == character) counter += 1;
    }

    return counter;
}

@end
@实现NSString(发生计数)
-(整数)字符的发生次数:(UniChar)字符
{
CFStringRef selfAsCFStr=(uu桥CFStringRef)self;
CFStringInlineBuffer-inlineBuffer;
CFIndex length=CFStringGetLength(selfAsCFStr);
cfStringInInlineBuffer(selfAsCFStr,&inlineBuffer,CFRangeMake(0,长度));
整数计数器=0;
对于(CFIndex i=0;i

这个方法比字符串分离的
组件快大约5倍。

现在我想到的第一件事是:

日志:


这是一个Swift 3工作版本,用于NSRange、Range、String和NSString!享受:)

///使用NSString和NSRange的所有范围
///通常与NSAttributedString一起使用
扩展字符串{
公共函数范围(搜索字符串的范围:字符串,选项:比较选项=.literal,搜索范围:NSRange?=nil)->[NSRange]{
让searchRange=searchRange??NSRange(位置:0,长度:self.length)
让subRange=range(of:searchString,options:options,range:searchRange)
如果subRange.location!=NSNotFound{
设nextRangeStart=subRange.location+subRange.length
设nextRange=NSRange(位置:nextRangeStart,长度:searchRange.location+searchRange.length-nextRangeStart)
return[subRange]+范围(of:searchString,options:options,searchRange:nextRange)
}否则{
返回[]
}
}
}
///使用字符串和范围的所有范围
///通常与NSAttributedString一起使用
扩展字符串{
公共函数范围(searchString:String,选项:CompareOptions=[],searchRange:Range?=nil)->[Range]{
如果let range=range(of:searchString,options:options,range:searchRange,locale:nil){

设nextRange=range.upperBound.不同Objective-C解决方案的性能比较

假设下面的所有方法都是NSString扩展(在
@实现NSString(CountOfOccurrences)
中)

作为一个示例,我使用了一个长度为100000000的随机生成的字符串,它使用了所有拉丁字符(
CharacterSet(charactersIn:“\u{0020}”…“\u{036F}”)
),要计数的字符是
@“a”

在版本配置的模拟器上对Xcode 10.3执行的测试

快速解决方案(精确的逐字符等效) 一个字符的计数有两种方法:使用或不使用。计数将不同,性能将受到根本影响。为了获得最快的结果,我们将执行精确的逐字符等效。以下四种解决方案给出了非常接近的性能结果

1.最快的解决方案:对愤世嫉俗的答案进行改编。 使用。这是所有场景中最快的解决方案:即使您将
NSLiteralSearch
替换为
kNilOptions
,您仍然比Pierrot387扫描仪解决方案更快

- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    return [[NSMutableString stringWithString:self] replaceOccurrencesOfString:stringToFind
                                                                    withString:stringToFind
                                                                       options:NSLiteralSearch
                                                                         range:NSMakeRange(0, self.length)];
}
2.第二快,另一个愤世嫉俗的答案。 使用

3.第三快,雅克解决方案。 使用。 看

4.第四快,将转换为Objective-C。 使用

慢解 以下解决方案不使用
NSLiteralSearch
,也不执行精确的逐字符等效。前两种解决方案可能比快速解决方案慢10倍,后一种可能慢100倍

5.慢解决方案:pierrot3887答案的改编 使用.太糟糕了,
NSScanner
不能提供精确的逐字符等效选项

- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    NSScanner *scanner = [NSScanner scannerWithString:self];
    scanner.charactersToBeSkipped = nil;
    scanner.caseSensitive = YES;
    NSUInteger numberOfOccurrences = 0;
    while (!scanner.isAtEnd) {
        [scanner scanUpToString:stringToFind intoString:nil];
        if (!scanner.isAtEnd) {
            numberOfOccurrences++;
            [scanner scanString:stringToFind intoString:nil];
        }
    }
    return numberOfOccurrences;
}
6.较慢的解决方案:gbaor解决方案 关于一行中的doable参数,请注意,上面给出的最快解也是一行

- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    return [self componentsSeparatedByString:stringToFind].count - 1;
}
7.最慢的解决方案:vikingosegundo答案的改编 使用


如果我正确理解了文档,这将给出集合中任何字符的范围。但我需要每个字符的计数。我的想法是保留字符字典->计数对,然后在给定索引处获取字符并增加其在字典中的计数…或者你可以迭代字符串并检查每个字符是否正确acter在你的集合中,如果它是递增的,那么它是递增的。我根本无法让它工作。我正在尝试计算空格的数量。@lawrence默认情况下,空格和空白被忽略
- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    return [[NSMutableString stringWithString:self] replaceOccurrencesOfString:stringToFind
                                                                    withString:stringToFind
                                                                       options:NSLiteralSearch
                                                                         range:NSMakeRange(0, self.length)];
}
- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    NSString *strippedString = [self stringByReplacingOccurrencesOfString:stringToFind
                                                               withString:@""
                                                                  options:NSLiteralSearch
                                                                    range:NSMakeRange(0, self.length)];
    return (self.length - strippedString.length) / stringToFind.length;
}
- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    //assert(stringToFind.length);
    NSUInteger count = 0;
    NSRange searchRange = NSMakeRange(0, self.length);
    NSRange foundRange;
    while ((void)(foundRange = [self rangeOfString:stringToFind options:NSLiteralSearch range:searchRange]), foundRange.length) {
        count += 1;
        NSUInteger loc = NSMaxRange(foundRange);
        searchRange = NSMakeRange(loc, self.length - loc);
    }
    return count;
}
- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    NSScanner *scanner = [NSScanner scannerWithString:self];
    scanner.charactersToBeSkipped = nil;
    scanner.caseSensitive = YES;
    NSUInteger numberOfOccurrences = 0;
    while (!scanner.isAtEnd) {
        [scanner scanUpToString:stringToFind intoString:nil];
        if (!scanner.isAtEnd) {
            numberOfOccurrences++;
            [scanner scanString:stringToFind intoString:nil];
        }
    }
    return numberOfOccurrences;
}
- (NSUInteger)countOccurrencesOfString:(NSString *)stringToFind
{
    return [self componentsSeparatedByString:stringToFind].count - 1;
}
- (NSUInteger)countOccurrencesOfCharacter:(NSString *)characterToFind
{
    __block NSUInteger counter = 0;
    [self enumerateSubstringsInRange:NSMakeRange(0, self.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        if ([characterToFind isEqualToString:substring]) counter += 1;
    }];
    return counter;
}