【问题标题】:Check IF one String contains the same characters as another string检查一个字符串是否包含与另一个字符串相同的字符
【发布时间】:2014-10-17 10:31:02
【问题描述】:

我正在尝试编写一个函数来确定一个NSString* 是否包含另一个NSString* 的字符。例如,请参考以下场景:

NSString *s1 = @"going";
NSString *s2 = @"ievngcogdl";

所以本质上,当这两个字符串之间发生比较时,它应该返回 true,因为第一个字符串 s1 与第二个字符串 s2 具有相同的字符。我可以使用NSCountedSet 吗?我知道这个类有一个方法containsObject:(id) 虽然我不认为这会解决我的问题。还有其他方法可以完成此功能并为我提供所需的结果吗?

【问题讨论】:

  • 对于少数情况,我可能会从第一个字符串中取出每个字符,将其放入 NSString 中,然后在第二个字符串中执行 rangeOfString。如果我必须对第二个字符串进行大量搜索,我会将字符(转换为 NSNumbers)放在一个集合中,并从第一个字符串中一次搜索一个字符。但是 Droppy 的方式可能是一个很好的折衷方案(尽管可以通过在开始之前将两个字符串提取为 unichar 数组来加速它)。

标签: ios objective-c string nsstring nscountedset


【解决方案1】:

我认为这种方法可能会相当慢,但我仍然喜欢它而不是 [NSString rangeOfCharacterFromSet:],因为它需要在每次比较时创建一个 NSCharacterSet 对象:

- (BOOL)string:(NSString *)string containsAllCharactersInString:(NSString *)charString {
    NSUInteger stringLen = [string length];
    NSUInteger charStringLen = [charString length];
    for (NSUInteger i = 0; i < charStringLen; i++) {
        unichar c = [charString characterAtIndex:i];
        BOOL found = NO;
        for (NSUInteger j = 0; j < stringLen && !found; j++)
            found = [string characterAtIndex:j] == c;
        if (!found)
            return NO;
    }
    return YES;
}

【讨论】:

  • 谢谢。如果我使用 [NSString rangeOfCharacterFromSet: @] 来实现它,会更快吗?即使每次比较我都会创建一个对象的实例?
  • @Maff 您必须确定时间才能确定,但​​是创建对象并不便宜,rangeOfCharacterFromSet: 无论如何都必须遍历字符串,所以我们不妨保持简单并执行我们自己的迭代。
  • 绝对同意。不过,我会尝试一下,看看我会怎么做。我会让你知道结果;在速度方面。感谢您的帮助。
  • 此解决方案不处理第一个字符串包含一个字母的单个实例但第二个字符串包含该字母的两个实例的情况 - 如您的示例“ievngcogdl”和“going”。尽管比较字符串中只有一个 g,但它为“ievngcodl”和“going”返回 YES
  • @Paulw11 我没有看到这是阅读问题的要求。
【解决方案2】:

这会起作用 -

-(BOOL) string:(NSString *)string1 containsInputString:(NSString *)string2 {

    // Build a set of characters in the string

    NSCountedSet *string1Set = [[NSCountedSet alloc]init];

    [string1 enumerateSubstringsInRange:NSMakeRange(0, string1.length)
                                options:NSStringEnumerationByComposedCharacterSequences
                             usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                                 [string1Set addObject:substring];
                             }];


    // Now iterated over string 2, removing characters from the counted set as we go
    for (int i=0;i<string2.length;i++) {
        NSRange range = [string2 rangeOfComposedCharacterSequenceAtIndex:i];
        NSString *substring = [string2 substringWithRange:range];
        if ([string1Set countForObject:substring]> 0) {
            [string1Set removeObject:substring];
        }
        else {
            return NO;
        }
    }
    return YES;
}

【讨论】:

  • 谢谢保罗,我肯定也会尝试这个解决方案!快速提问,根据上述逻辑,看起来string1 方法参数是包含较长字符集的那个?那是对的吗?因此,从我上面的示例中,它将是:s2?
  • 是的,我切换了 string1 和 string2 以使方法名称更好:)
  • 如果你使用这个,请确保你使用我更新的代码 - 初始版本没有正确初始化计数集
  • 我不明白你的评论。它适用于您问题中的测试用例。失败的测试用例是什么
  • 抱歉 Paul 我相信我正在调用名为 containsString 的字符串的内置方法名称,它只返回完全匹配的内容。现在一切都很好。
【解决方案3】:

正则表达式是检查此类条件并检查this link一次的最佳方法

下面我正在为您的解决方案添加代码,请检查一次

  NSString *s1 = @"going"
  NSString *s2 = @"ievngcogdl";

  if ([self string:s1 containsSameCharacterofString:s2]) {

            NSLog(@"YES");

  }


    - (BOOL)string:(NSString *)str containsSameCharacterofString:(NSString *)charString
    {

        if (charString.length >= str.length) {

            NSError *error = nil;
            NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"^[%@]+$", charString] options:NSRegularExpressionCaseInsensitive error:&error];

            NSRange textRange = NSMakeRange(0, str.length);
            NSRange matchRange = [regex rangeOfFirstMatchInString:str options:NSMatchingReportProgress range:textRange];

            return (matchRange.location != NSNotFound);

        }
        else {

            return NO;
        }

    }

【讨论】:

  • 它与[NSString isEqualToString:] 有什么不同,除了更昂贵和使用起来更麻烦?
  • 对于大字符串,遍历整个字符串会很昂贵,所以最好使用正则表达式来处理这种类型的条件。
  • 试试NSString *s2 = @"i";,告诉我方法返回什么。
  • 修改答案检查一次。
【解决方案4】:
BOOL containsString = [@"Hello" containsString:@"llo"];
if (containsString) {
    // Do Stuff
}

【讨论】:

  • 它附带了 Xcode 6 中最新构建的 Foundation 框架。它像 NSPredicate 一样工作,即 [NSPredicate predicateWithFormat:@"SELF CONTAINS %@", string];我认为答案/方法名称是不言自明的,它有效,因此 +1。
  • 这不是NSString 上的方法,请阅读Apple 文档(developer.apple.com/library/mac/documentation/Cocoa/Reference/…) 这个文档在哪里?因为它不存在,所以这就是 4 倍反对票的原因。这个答案不正确
  • 这是在基础框架的 NSString.h 中:/* containsString: returns YES if the target string is contained within the receiver. Same as calling rangeOfString:options: with no options, thus doing a case-sensitive, non-literal search. localizedCaseInsensitiveContainsString: is the case-insensitive variant. Note that it takes the current locale into effect as well. Locale-independent case-insensitive operation, and other needs can be achieved by calling rangeOfString:options:range:locale: directly. */ - (BOOL)containsString:(NSString *)aString NS_AVAILABLE(10_10, 8_0);
  • 如果这让你满意,请你把-分拿走
  • 无论该方法是否存在,它都不符合问题的要求,因为他们不是在寻找子字符串,而是在寻找任何顺序的字母
猜你喜欢
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多