我知道我可以检查一个字符串是否包含另一个像这样的字符串
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"]
答案 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
现在我可以创建像
这样的subPredicatesNSArray *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计算魔法!
isEqual:
方法,以匹配句子中是否有单词(也可以在那里设置!)NS(*)Set
对象