2013-04-08 95 views
0

我有一个核心数据结构如下:核心数据过滤

Business <-------->> Employee <-------->> Address

每个企业都有多个员工和每个员工可以有多个地址。

从Business对象中,我希望能够获得指定特定条件的所有Address对象中的NSArrayNSSet。例如。所有的街道名称都必须是唯一的。

我知道我可以覆盖isEqual:但我猜这将会有意想不到的结果。否则,我一直在研究使用valueForKeyPath:@"@distinctUnionOfObjects",但我认为我不能通过一个条件。

下面是一些代码,我到目前为止有:

NSMutableArray *addressArray = [NSMutableArray array]; 
    NSArray *employees = [Employee sortedArray]; 

    //loop through employees 
    for (Employee *employee in employees) { 
     for (Address *address in employee.addresses) { 
      [addressArray addObject:address]; 
     } 
    } 

    //filter out duplicates 
    addressArray = [addressArray valueForKeyPath:@"@distinctUnionOfObjects.city"]; 

此代码给了我独一无二的城市的名单,但是,我想包含Address对象具有唯一city值(或其他一些条件的集合)。

+0

问题是没有独特的解决方案。如果同一城市有多个地址,应选择哪个地址对象?下面的解决方案选择“第一个”,这是随机的,因为数组中的对象没有明确定义的顺序。 – 2013-04-09 05:12:03

+0

的确如此。我用这个简单的例子。我有一个基于其他一些属性生成的自定义属性。在我的情况下,第一个是好的,但我用它作为基于属性过滤唯一对象的简单示例。 – danielbeard 2013-04-09 05:18:47

回答

0

我找到了一种与LinqToObjectiveC library做到这一点:

NSArray* addressesWithUniqueCities = [input distinct:^id(id address) { 
    return [address city]; 
}]; 

查看源,底层实现如下:

typedef id (^Selector)(id item); 

-(NSArray *)distinct:(Selector)keySelector 
{ 
    NSMutableSet* keyValues = [[NSMutableSet alloc] init]; 
    NSMutableArray* distinctSet = [[NSMutableArray alloc] init]; 
    for (id item in self) { 
     id keyForItem = keySelector(item); 
     if (![keyValues containsObject:keyForItem]) { 
      [distinctSet addObject:item]; 
      [keyValues addObject:keyForItem]; 
     } 
    } 
    return distinctSet; 
} 

我的最终代码结束了:

NSMutableArray *addressArray = [NSMutableArray array]; 
    NSArray *employees = [Employee sortedEmployees]; 

    //loop through employees 
    for (Employee *employee in employees) { 
     for (Address *address in employee.addresses) { 
      [addressArray addObject:address]; 
     } 
    } 

    //filter out duplicates 
    NSArray *distinctAddressArray = [addressArray distinct:^id(id address) { 
     return [address addressLine]; 
    }]; 

    return distinctAddressArray; 
0

我不确定这是你的意思,但你可以尝试像这样:(未经测试)

+ (NSMutableArray*) addressesForBusiness:(Business*)business 
         sectionProperty:(NSString*)sectionProperty 
{ 

    NSFetchRequest* request = [[NSFetchRequest alloc] initWithEntityName:@"Address"]; 
    request.predicate = [NSPredicate predicateWithFormat:@"employee.business == %@",business.objectID]; 
    request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:sectionProperty ascending:YES]]; 

    NSArray* addresses = [business.managedObjectContext executeFetchRequest:request error:NULL]; 
    NSMutableArray* sections = [NSMutableArray new]; 
    NSMutableArray* currentSection = [NSMutableArray new]; 
    NSManagedObject* prevAddress = nil; 
    for (NSManagedObject* address in addresses) { 
     if (prevAddress && ([[address valueForKey:sectionProperty] isEqual:[prevAddress valueForKey:sectionProperty]])) { 
      currentSection = [NSMutableArray new]; 
      [sections addObject:currentSection]; 
     } 
     prevAddress = address; 
     [currentSection addObject:address]; 
    } 

    return sections; 
} 

这将返回阵列,其中每个阵列内部保持具有相同属性值的对象的阵列。在您的示例中,您可以拨打:

[[self class] addressesForBusiness:someBusiness sectionProperty:addressLine];