检查String是否包含数组中的任何String

时间:2015-06-22 18:35:20

标签: ios objective-c arrays loops nsstring

我知道我可以检查一个字符串是否包含另一个像这样的字符串

NSString *string = @"hello bla bla";
if ([string rangeOfString:@"bla"].location == NSNotFound) {
  NSLog(@"string does not contain bla");
} else {
  NSLog(@"string contains bla!");
}

但是如果我有NSArray *arary = @[@"one",@"two", @"three", @"four"]并且我想检查一个字符串是否包含其中一个而不仅仅是循环或者有一堆或者是(||)。所以它会是这样的

if (array contains one or two or three or four) {
//do something
}

但是,如果我有一个更长的数组,这会变得单调乏味,所以有另一种方式,而不仅仅是循环吗?

修改

我想检查myArray是否在valuesArray中有任何值?

valuesArray =@[@"one",@"two", @"three", @"four"];
myArray = [@"I have one head", @"I have two feet", @"I have five fingers"]

输出

outputArray = @[@"I have one head", @"I have two feet"]

3 个答案:

答案 0 :(得分:3)

你去了:

NSArray* arrRet = [myArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id  __nonnull evaluatedObject, NSDictionary<NSString *,id> * __nullable bindings) {
    for(NSString* val in valuesArray) {
        if ([evaluatedObject rangeOfString:val].location != NSNotFound)
            return true;
    }
    return false;
}]];

arrRet包含两个所需的字符串。

稍微有点魔力,你可以在不编写循环的情况下获得代码:P

NSArray* arrRet = [myArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id  evaluatedObject, NSDictionary<NSString *,id> * bindings) {
    BOOL __block match = false;
    [valuesArray enumerateObjectsUsingBlock:^(id  __nonnull obj, NSUInteger idx, BOOL * __nonnull stop) {
        *stop = match = [evaluatedObject rangeOfString:obj].location != NSNotFound;
    }];
    return match;
}]];

答案 1 :(得分:1)

您可以使用NSCompoundPredicate

NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];

您的subPredicates必须如此

(
    SELF CONTAINS[c] "one",
    SELF CONTAINS[c] "two",
    SELF CONTAINS[c] "three",
    SELF CONTAINS[c] "four"
)

到达那里
NSArray *array = @[@"one", @"two", @"three", @"four"]

你可以使用for循环,但是当你反对时,让我们作弊:

通过使用类别I每个NSArray功能映射,但不使用循环,我使用枚举

@interface NSArray (Map)
-(NSArray *) vs_map:(id(^)(id obj))mapper;
@end

@implementation NSArray (Map)

-(NSArray *)vs_map:(id (^)(id))mapper
{
    NSMutableArray *mArray = [@[] mutableCopy];
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        id mapped = mapper(obj);
        [mArray addObject:mapped];
    }];

    return [mArray copy];
}

@end

现在我可以创建像

这样的subPredicates
NSArray *subPredicates = [arary vs_map:^id(NSString *obj) {
        return [NSPredicate predicateWithFormat:@"SELF contains[c] %@", obj];
}];

并创建像

这样的复合谓词
NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];

并使用它

BOOL doesContain = [predicate evaluateWithObject:string];

etvoilà:没有(明显的)循环,而在枚举中隐藏了一个,并且可能在谓词中也是如此。

现在有了改变的问题,你基本上要求过滤。您可以使用相同的谓词:

NSArray *testarray = @[@"I have one head", @"I have two feet", @"I have five fingers"];
NSArray *arary = @[@"one",@"two", @"three", @"four"];

NSArray *subPredicates = [arary vs_map:^id(NSString *obj) {
    return [NSPredicate predicateWithFormat:@"SELF contains[c] %@", obj];
}];

NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
NSArray *results = [testarray filteredArrayUsingPredicate:predicate];

results现在包含

(
    I have one head,
    I have two feet
)

完整的代码

#import <Foundation/Foundation.h>

@interface NSArray (Map)
-(NSArray *) vs_map:(id(^)(id obj))mapper;
@end

@implementation NSArray (Map)

-(NSArray *)vs_map:(id (^)(id))mapper
{
    NSMutableArray *mArray = [@[] mutableCopy];
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        id mapped = mapper(obj);
        [mArray addObject:mapped];
    }];

    return [mArray copy];
}

@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {


        NSArray *testarray = @[@"I have one head", @"I have two feet", @"I have five fingers"];
        NSArray *arary = @[@"one",@"two", @"three", @"four"];

        NSArray *subPredicates = [arary vs_map:^id(NSString *obj) {
            return [NSPredicate predicateWithFormat:@"SELF contains[c] %@", obj];
        }];

        NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
        NSArray *results = [testarray filteredArrayUsingPredicate:predicate];

    }
    return 0;
}

答案 2 :(得分:0)

除了我欺骗我的另一个问题,这里有一个想法,如何真正避免时间成本高昂的循环:使用Set计算魔法!

  • 创建了一个“Sentence”类,用字符串实例化它来测试
  • 创建了一个“Word”类,用于搜索
  • 覆盖两个类的isEqual:方法,以匹配句子中是否有单词(也可以在那里设置!)
  • 将这些放入阵列。
  • 从此数组创建一个NS(*)Set对象
  • 将所有单词放入一组
  • 执行联盟。