【问题标题】:Filter NSArray of objects to have unique property object过滤对象的 NSArray 以具有唯一的属性对象
【发布时间】: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。

【问题讨论】:

    标签: ios objective-c nspredicate


    【解决方案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 类中)。之后通过首先检查将经理添加到数组中,如果数组已经包含具有此类帐户的经理。检查以下可能的解决方案:

    1. 覆盖管理器 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];
    }
    
    1. 覆盖 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];
    }
    
    1. 过滤器数组:
      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-06
        • 2013-06-25
        • 2019-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多