过滤对象的 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 以具有唯一的属性对象的主要内容,如果未能解决你的问题,请参考以下文章

NSArray:删除具有重复属性的对象

使用 NSPredicate 的不同对象

过滤 NSFetchedResultsController 以删除具有相同名称的对象

如何创建集合扩展以在具有属性的集合中查找唯一对象?

通过对具有匹配 ID 号的对象进行分组来重建 NSArray?

通过属性过滤掉相似对象的谓词