56 votes

Nombre d'occurrences d'une sous-chaîne dans une chaîne NSString?

Comment puis-je obtenir le nombre de fois qu'une chaîne NSString (par exemple, @"cake" ) apparaît dans une chaîne plus grande NSString (par exemple, @"Cheesecake, apple cake, and cherry pie" )?

Je dois le faire sur beaucoup de chaînes, donc quelle que soit la méthode que j'utilise, elle doit être relativement rapide.

Merci!

98voto

Matthew Flaschen Points 131723

Ce n'est pas testé, mais devrait être un bon début.

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

70voto

gwdp Points 648

Une expression régulière comme celle ci-dessous devrait faire l'affaire sans interaction en boucle ...

Édité

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

Disponible uniquement sur iOS 4.x et supérieurs.

23voto

Dave DeLong Points 156978

Vous pouvez le faire de différentes manières. Vous pouvez appeler itérativement rangeOfString:options:range: , ou vous pouvez faire quelque chose comme:

 NSArray * portions = [aString componentsSeparatedByString:@"cake"];
NSUInteger cakeCount = [portions count] - 1;
 

EDIT Je réfléchissais de nouveau à cette question et j’ai écrit un algorithme linéaire pour effectuer la recherche (linéaire par rapport à la longueur de la chaîne de la botte de foin):

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

11voto

Dash Points 1982

Une solution plus rapide à taper, mais probablement moins efficace.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X