1

我想检查一个 NSString 是否包含每个可能的数字(0-9)超过 5 次。我不需要知道哪个数字或多少次,我只是希望它返回 TRUE 或 False,以确定字符串中是否包含任何数字超过 5 次。我希望它尽可能高效。

我已经给它一些想法,并且要解决它的漫长方法是将所有 10 个数字(同样是 0-9)放在一个数组中,然后循环遍历每个数字,将其与字符串进行比较。如果字符串中有超过 5 个匹配项,则放置一个返回 true 的标志。

谁能告诉我是否有解决这个问题的“更好”或更有效的方法?

谢谢!

4

4 回答 4

3

这可能不是“最好”的做事方式,但它对我来说是最有趣的方式,它很好地利用了 Foundation 使用字符集、计数集和基于块的字符串枚举。

// 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);
                                  }
                              }
                          }];

如果您不让它停止,那么它将继续计算该字符串中所有数字的出现次数。

如果您记录计数集,则如下所示(方括号内的数字为计数):

<NSCountedSet: 0xa18d830> (3 [1], 1 [6], 4 [1], 2 [1], 5 [6])
于 2013-08-14T11:39:58.137 回答
2

此代码尝试尽可能提高性能。

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;
}
于 2013-08-14T10:42:40.163 回答
0

使用以下代码检查字符串是否包含 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++; 
    }
  }
于 2013-08-14T10:34:02.473 回答
-1
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]];
            }
于 2013-08-14T10:24:15.583 回答