过滤对象的 NSArray 以具有唯一的属性对象
Posted
技术标签:
【中文标题】过滤对象的 NSArray 以具有唯一的属性对象【英文标题】:Filter NSArray of objects to have unique property object 【发布时间】:2015-03-07 23:18:46 【问题描述】:我有 Manager 对象和 Account 对象。 Manager 对象有一个属性 Account。
有一个 NSArray 的 Manager 对象,需要 Account 唯一!
示例数组:
NSArray *managers = @[Manager1(has Account1), Manager2(has Account1), Manager3(has Account1), Manager4(has Acconut2), Manager5(has Account2)];
我需要一个只有 Manager1 和 Manager4 的 NSArray。
【问题讨论】:
【参考方案1】:你需要的是 distinctUnionOfObjects
[managers valueForKeyPath:@"@distinctUnionOfObjects.Account"];
这里是documentation
@distinctUnionOfObjects @distinctUnionOfObjects 运算符返回一个数组,该数组包含由运算符右侧的键路径指定的属性中的不同对象。
以下示例返回交易中的交易的收款人属性值,并删除了任何重复值:
NSArray *payees = [transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];
生成的 payees 数组包含以下字符串:Car Loan、General Cable、Animal Hospital、Green Power、Mortgage。
@unionOfObjects 运算符类似,但不会删除重复对象。
【讨论】:
这是最好的答案,应该是公认的。 +1 这将返回 Account 的数组对象而不是 Managers 的对象。【参考方案2】:您需要在 Manager 类中覆盖 isEqual 方法(也可能在 Account 类中)。之后通过首先检查将经理添加到数组中,如果数组已经包含具有此类帐户的经理。检查以下可能的解决方案:
-
覆盖管理器 isEqual
- (BOOL)isEqual:(id)object
if (object == self)
return YES;
else if (![object isKindOfClass:[Manager class]])
return NO;
Manager *manager = (Manager *)object;
return [self.account isEqual:manager.account];
-
覆盖 Account isEqual(注意!仅在需要时)
- (BOOL)isEqual:(id)object
if (object == self)
return YES;
else if (![object isKindOfClass:[Account class]])
return NO;
Account *account = (Account *)object;
return [self.someUniqueId isEqual:account.someUniqueId];
-
过滤器数组:
NSMutableArray *filteredManagers = [NSMutableArray array];
[managers enumerateObjectsUsingBlock:^(Manager *manager, NSUInteger idx, BOOL *stop)
if (![filteredManagers containsObject:manager])
[filteredManagers addObject:manager];
];
【讨论】:
没有给出创建Account和Manager的条件,所以KVC不能工作 顺便说一句:如果您已经使用isEqual:
,请同时实现hash
并使用NSSet 和子类而不是迭代数组。【参考方案3】:
NSArray *managers = // The 5 Manager objects in your example
NSMutableArray *filteredManagers = [NSMutableArray array];
NSMutableArray *accountsManaged = [NSMutableArray array];
for (Manager *manager in managers)
if (![accountsManaged containsObject:manager.account])
[filteredManagers addObject:manager];
[accountsManaged addObject:manager.account];
// filteredManagers now contains Manager1 and Manager4
【讨论】:
【参考方案4】:假设您有一个唯一 (!) 包含帐户的单独数组,并进一步假设您的类符合键值,我将枚举该帐户数组并找到管理每个帐户的所有经理。然后选择第一个经理并将其添加到一个新数组中,如下所示:
NSMutableArray *filteredManagers = [NSMutableArray array];
for (Account *account in accounts)
NSArray *managersForAccount = [managers filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"account == %@", account];
[filteredManagers addObject:[managersForAccount firstObject]];
// do something with filteredManagers
【讨论】:
以上是关于过滤对象的 NSArray 以具有唯一的属性对象的主要内容,如果未能解决你的问题,请参考以下文章
过滤 NSFetchedResultsController 以删除具有相同名称的对象