Teddy13
Teddy13

Reputation: 3854

Check if string contains occurence of digit

I would like to check if a NSString contains each digit possible (0-9) more then 5 times. I do not need to know which digit or how many times, I simply want it to return TRUE or False for whether any of the digits are contained more then 5 times in the string. I would like it to be as efficient as possible.

I have given it some thought and the long way of going about it would be to place all 10 digits (again 0-9) in an array and then loop through each digit comparing it to the string. If there are more than 5 matches within the string, place a flag that will return true.

Can anyone tell me if there is a "better" or more efficient way of going about this problem?

Thank you!

Upvotes: 1

Views: 1207

Answers (4)

David Rönnqvist
David Rönnqvist

Reputation: 56625

This may not be the "best" way of doing things but it was the most fun way of doing it for me and it takes quite good advantage of Foundation using characters sets, counted sets and block based string enumeration.

// Your string
NSString *myString = @"he11o 12345 th1s 55 1s 5 very fun 55 1ndeed.";

// A set of all numeric characters
NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
NSUInteger digitThreshold = 5;

// An emtpy counted set
NSCountedSet *numberOccurances = [NSCountedSet new];

// Loop over all the substrings as composed characters
// this will not have the same issues with e.g. Chinese characters as
// using a C string would. (Available since iOS 4)
[myString enumerateSubstringsInRange:NSMakeRange(0, myString.length)
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                              // Check if substring is part of numeric set of characters
                              if ([substring rangeOfCharacterFromSet:numbers].location != NSNotFound) {
                                  [numberOccurances addObject:substring];
                                  // Check if that number has occurred more than 5 times
                                  if ([numberOccurances countForObject:substring] > digitThreshold) {
                                      *stop = YES;
                                      // Do something here based on that fact
                                      NSLog(@"%@ occured more than %d times", substring, digitThreshold);
                                  }
                              }
                          }];

If you don't let it stop then it will continue to count the number of occurrences for all the digits in that string.

If you log the counted set is looks like this (number within square brackets are count):

<NSCountedSet: 0xa18d830> (3 [1], 1 [6], 4 [1], 2 [1], 5 [6])

Upvotes: 3

Nikolai Ruhe
Nikolai Ruhe

Reputation: 81868

This code tries to be as performant as possible.

BOOL checkDigits(NSString *string)
{
    // get the raw UTF-16 code fragments, hopefully without a copy
    const UniChar *characters = CFStringGetCharactersPtr((__bridge CFStringRef)string);
    NSData *characterData = nil;
    if (characters == NULL) {
        characterData = [string dataUsingEncoding:NSUTF16StringEncoding];
        characters = [characterData bytes];
    }

    // initialize 10 individual counters for digits
    int digitCount[10] = {};
    NSUInteger length = [string length];

    // loop over the characters once
    for (NSUInteger i = 0; i != length; ++i) {
        UniChar c = characters[i];

        // UTF-16 encodes ASCII digits as their values
        if (c >= '0' && c <= '9') {
            int idx = c - '0';
            if (digitCount[idx] == 4)
                return YES;
            digitCount[idx] += 1;
        }
    }

    // keep the NSData object alive until here
    [characterData self];

    return NO;
}

Upvotes: 2

Divya Bhaloidiya
Divya Bhaloidiya

Reputation: 5064

Use following code to check string contain 0-9 :

NSUInteger count = 0, length = [yourString length];
    NSRange range = NSMakeRange(0, length); 
    while(range.location != NSNotFound)
   {
     range = [yourString rangeOfString: @"hello" options:0 range:range];
     if(range.location != NSNotFound)
     {
        range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
       count++; 
    }
  }

Upvotes: 0

NHS
NHS

Reputation: 409

NSString *materialnumber =[[self.documentItemsArray objectAtIndex:indexPath.row] getMATERIAL_NO];
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES '[0-9*]+'"];
            if ([predicate evaluateWithObject:materialnumber])
            {
                materialnumber = [NSString stringWithFormat:@"%d",[materialnumber intValue]];
            }

Upvotes: -1

Related Questions