使用 NSPredicate 过滤对象和键(需要拆分)
Posted
技术标签:
【中文标题】使用 NSPredicate 过滤对象和键(需要拆分)【英文标题】:Using NSPredicate to filter an object and a key(that needs to be split) 【发布时间】:2013-06-14 06:23:14 【问题描述】:我设置了以下字典(对象,键)
0, "10;0.75,0.75"
1, "0;2.25,2.25"
3, "1;3.5,2.0"
4, "1;4.5,3.0"
5, "2;6.0,5,0"
我要过滤的内容将基于对象和键。该对象是一个 NSNumber。关键是一个字符串,但我真的不想要整个字符串。我想拆分由分号分隔的字符串并获取拆分的第一个索引,这将根据我要查找的对象生成字符串 10,0,1,1 或 2。
作为一个具体的例子:
是否有任何键等于@"1" 与大于 3 的对象。
在这种情况下,我应该期待返回 YES,因为在我进行拆分之后,对象 4 有一个等于 @"1" 的键。
我想我正在寻找一种聪明的方法来定义一个 NSPredicate 来对由分号分隔的键进行拆分,然后根据它进行过滤(比较等)。如果您有任何问题或需要更多信息,请告诉我。
【问题讨论】:
如果您可以格式化字典,那将是进行过滤的最简单方法。 可以使用谓词,但是需要自己写比较方法。 是的,我想定义一个谓词而不进行比较。我已经想到了 Anupdas 的回答。 【参考方案1】:我能想到的一个非常幼稚的实现
- (BOOL)hasKey:(NSString *)key withValueGreaterThan:(id)object
NSDictionary *dictionary = @@"10;0.75,0.75": @0,
@"0;2.25,2.25" : @1,
@"1;3.5,2.0" : @3,
@"1;4.5,3.0" : @4,
@"2;6.0,5,0" : @5;
NSPredicate *keyPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH %@",key];
NSArray *filteredKeys = [[dictionary allKeys]filteredArrayUsingPredicate:keyPredicate];
for (NSString *k in filteredKeys)
NSNumber *value = dictionary[k];
if (value>object)
return YES;
return NO;
使用
BOOL hasValue = [self hasKey:@"1;" withValueGreaterThan:@3];
【讨论】:
这个答案是先写的,是关于我已经写的但想在不写循环片段的情况下定义谓词。 更正-您还需要先拆分密钥,然后才能比较是吗?另外,我不想只获取大于对象编号的所有密钥。如果我的字典有 100,000 个项目,那将在循环中为我节省一些迭代。是的?也许对对象(allKeysForObject(id))而不是 allKeys 进行比较。 好吧,我想没有一种简单的方法可以像我想的那样获取 allObjects,所以也许你必须按照自己的方式去做......除非我错过了一个方法?我一直想知道为什么他们允许你获取所有对象。 @cspam 没有密钥分离。这里的问题是包含分号,否则如果你只给'1'键'10'也将通过测试。当我们查字典的时候,你已经知道相等的关键和条件了。所以不需要拆分密钥。 似乎有一个错误 - 如果 key 为 3 - 它会抓取以 3 - 30,300,31 等开头的所有项目。【参考方案2】:示例代码:
NSDictionary* dict = @ @"10;0.75,0.75":@0,
@"0;2.25,2.25":@1,
@"1;3.5,2.0":@3,
@"1;4.5,3.0":@4,
@"2;6.0,5,0":@5;
__block NSString* foundKey = nil;
[dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber* obj, BOOL *stop)
//here goes condition
//get substr
NSArray* arr = [key componentsSeparatedByString:@";"];
int num = [[arr objectAtIndex:0]integerValue];
if ((num == 1)&&([obj integerValue]>3))
foundKey = key;
stop = YES;
];
if (foundKey)
NSLog(@"%@:%@",foundKey,[dict objectForKey:foundKey]);
【讨论】:
【参考方案3】:只需使用以下方法:
-(BOOL)filterFromDictionary:(NSDictionary*)dict keyEqual:(NSString*)key greaterthanObj:(NSString*)obj
NSArray *allKeys = [dict allKeys];
for (NSString *eachkey in allKeys)
NSString *trimmedKey = [self trimKeyuntill:@";" fromString:eachkey];
NSString *trimmedValue = [dict objectForKey:eachkey];
if ([trimmedKey isEqualToString:key] && [trimmedValue intValue] > [obj intValue])
return YES;
return NO;
使用您的字典调用上述方法,例如:
NSDictionary *dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1",@"1",@"3",@"4",@"5", nil] forKeys:[NSArray arrayWithObjects:@"10;0.75,0.75",@"0;2.25,2.25",@"1;3.5,2.0",@"1;4.5,3.0",@"2;6.0,5,0", nil]];
[self filterFromDictionary:dict keyEqual:@"1" greaterthanObj:@"3"]
我假设你所有的对象都是 nsstrings。否则更改 intValue
【讨论】:
以上是关于使用 NSPredicate 过滤对象和键(需要拆分)的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 NSPredicate 过滤 Core Data 托管对象?