如何使用一个数组作为另一个数组的谓词?

时间:2013-10-28 15:51:28

标签: ios ios7 nsarray

NSArray *arrClient = [[NSArray alloc] initWithObjects:@"record 1", @"record 2", nil];
NSArray *arrServer = [[NSArray alloc] initWithObjects:@"record 1", @"record 3", nil];

arrServer上我想应用谓词来仅过滤那些arrClient中尚未存在的条目。例如在这种情况下,record 1存在于两个数组中并且应该被忽略,因此只返回一个带有“record 3”字符串的数组的数组。

这可能吗?

更新

以下答案很棒。我相信我需要给出一个真实的例子来验证我所做的事情是否有意义。 (我仍然在下面给出一个紧凑版本)

现在clientItems的类型为FTRecord(核心数据)

@interface FTRecord : NSManagedObject
...
@property (nonatomic) NSTimeInterval recordDate;

@end

@implementation FTRecord
...
@dynamic recordDate;

@end

下面这个类是从REST服务解析json的持有者。因此,我们之前提到的serverItem将属于这种类型。

@interface FTjsonRecord : NSObject <JSONSerializable>
{

}

@property (nonatomic) NSDate *recordDate;

@implementation FTjsonRecord

- (NSUInteger)hash
{
    return [[self recordDate] hash];
}

- (BOOL)isEqual:(id)object
{
    if ([object isKindOfClass:[FTjsonRecord self]]) {
        FTjsonRecord *other = object;
        return [[self recordDate] isEqualToDate:[other recordDate]];
    }
    else if ([object isKindOfClass:[FTRecord self]]) {
        FTRecord *other = object;
        return [[self recordDate] isEqualToDate:[NSDate dateWithTimeIntervalSinceReferenceDate:[other recordDate]]];
    }
    else {
        return NO;
    }
}

按照Wain的例子,这似乎工作正常。现在这可行吗? 请记住,serverItems只是临时的,仅用于与服务器同步,并将被丢弃。 clientItems仍然存在。

更新2:

这次我正在尝试Manu的解决方案:

我在我的客户端DBStore上创建了这个方法,该方法由谓词调用。 我不能使用containsObject的原因是因为serverItems和clientItems中的类类型不是同一类型。

-(BOOL)recordExistsForDate:(NSDate *)date
{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"recordDate == %@", date];
    NSArray *arr = [allRecords filteredArrayUsingPredicate:predicate];
    if (arr && [arr count] > 0) {
        return YES;
    } else {
        return NO;
    }
}

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(FTjsonRecord *evaluatedObject, NSDictionary *bindings) {
                return ![store recordExistsForDate:[evaluatedObject recordDate]];
}];

NSSet *set = [[serverRecords items] filteredSetUsingPredicate:predicate]; 

这个解决方案令我担心的是,我的clientItems(allRecords)的线性读取。我不确定在阵列上使用谓词的效率如何,想知道是否有更好的方法来实现这一点。

2 个答案:

答案 0 :(得分:1)

您可以使用NSSet来获取其他集合的联合,交集和差异(减号)。这更准确地匹配您要做的事情。

NSMutableSet *serverItems = [[NSMutableSet alloc] init];
[arrServerItems addObjectsFromArray:arrServer];

NSSet *clientItems = [[NSSet alloc] init];
[clientItems addObjectsFromArray:arrClient];

[arrServerItems minus:clientItems];

这确实删除了订购信息。

对于谓词,您可以使用:

NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", arrClient];

答案 1 :(得分:0)

取决于您要使用的谓词:

您可以使用此

来使用一组参数
[NSPredicate predicateWithFormat:<#(NSString *)#> argumentArray:<#(NSArray *)#>];

使用数组中的对象构建谓词

或使用带块的谓词

[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    <#code#>
}]

并在块中展开对象,将其与数组中的对象进行比较

您可以做的可能检查是:

return ![arrClient containsObject:evaluatedObject];

将排除arrClient中包含的对象

containsObject:使用'isEqual:'来比较对象