programing

NSString에서 하위 문자열의 발생 횟수?

nasanasas 2020. 12. 26. 15:30
반응형

NSString에서 하위 문자열의 발생 횟수?


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");
}

하위 문자열뿐만 아니라 단어 수를 계산 하려면 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's answer was a good start for me. Here is what I ended up using in the form of a method. I took a slightly different approach to the loop. This has been tested with empty strings passed to stringToCount and text and with the stringToCount occurring as the first and/or last characters in text.

I use this method regularly to count paragraphs in the passed text (ie. stringToCount = @"\r").

Hope this of use to someone.

    - (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;
   }

Example call assuming the method is in a class named 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++;

  }

 }

No built-in method. I'd suggest returning a c-string and using a common c-string style algorithm for substring counting... if you really need this to be fast.

If you want to stay in Objective C, this link might help. It describes the basic substring search for NSString. If you work with the ranges, adjust and count, then you'll have a "pure" Objective C solution... albeit, slow.


-(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);
    }

}

ReferenceURL : https://stackoverflow.com/questions/2166809/number-of-occurrences-of-a-substring-in-an-nsstring

반응형