【问题标题】:remove object from NSMutableArray by key按键从 NSMutableArray 中删除对象
【发布时间】:2014-12-30 02:14:31
【问题描述】:
NSMutableArray *array = [NSMutableArray arrayWithObjects:@{@"name":@"Jenny",@"age":@23},@{@"name":@"Daisy",@"age":@27},nil];

是否可以在数组的字典对象中按键删除对象?

例如。按年龄删除对象 = 27

【问题讨论】:

  • 你的意思是要删除第二本词典?

标签: ios nsmutablearray nsdictionary


【解决方案1】:

要从 NSArray 中过滤对象,请调用 filteredArrayUsingPredicate:

NSArray *array = @[@{@"name":@"Jenny",@"age":@23},@{@"name":@"Daisy",@"age":@27}];
NSArray *array2 =
  [array filteredArrayUsingPredicate:
   [NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *d) {
      return ![[obj valueForKey:@"age"] isEqual:@27];
  }]];

现在array2 是所需的数组 - 它是第一个没有年龄为 27 岁的数组。

顺便说一句,我知道这不是你问的,但是这种事情是切换到 Swift 的一个很好的理由。它太简单了;这类问题就像 Swift 的一个活生生的霓虹灯技术广告:

let array = [["name":"Jenny", "age":23],["name":"Daisy", "age":27]]
let array2 = array.filter {$0["age"] != 27}

【讨论】:

  • 非常有趣,之前从未在核心数据之外使用过谓词。这是否仍然在最坏的情况下执行 n 次迭代的搜索,还是比正常的迭代过程更有效?
  • @Mike 这只是一个循环。
【解决方案2】:

您可以使用NSPredicate 创建一个缺少不需要的条目的新数组。 NSPredicate 类似于数据库查询,输入 NSArray 表示数据库,输出数组是查询的响应。

NSArray *array = @[  @{@"name":@"Jenny",@"age":@23},
                     @{@"name":@"Daisy",@"age":@27}  ];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age != 27"];
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];

NSLog( @"%@", array );
NSLog( @"%@", filtered );

【讨论】:

    【解决方案3】:

    我不确定是否有更直接的方法,但一种方法是简单地遍历数组并测试值。您不能在枚举时改变数组,这意味着您不能在遍历它时删除一个对象,因此一种方法是获取与您的条件匹配的对象的索引,如果找到一个,打破并删除该项目那个索引。类似于以下内容:

    NSInteger indexToDelete = -1;
    
    for (NSInteger i = 0; i < array.count; i++) {
       NSDictionary *dict = array[i];
    
       if ([dict[@"age"] integerValue] == 27) {
          indexToDelete = i;
          break;      
       }
    }
    
    if (indexToDelete > 0) {
       [array removeObjectAtIndex:indexToDelete];
    }
    

    对使用 filteredArrayUsingPredicate 的其他答案很感兴趣,我对性能很好奇,并决定使用 Xcode 的 measureBlock 功能进行并行性能测试。遍历包含 1,000 个字典的数组,从每个数组中删除一个与整数值匹配的项目,并比较该项目何时非常接近数组的开头、数组的中间和数组的结尾,两个版本倾向于在另一个秒的几千分之内完成,谓词过滤器在每种情况下都稍微快一点。 (我们谈论的是 0.269 秒与 0.261 秒)

    考虑到这一点,我认为在任何主要意义上都比另一个更好,它只是归结为偏好。我确实认为filteredArrayUsingPredicate 方法更干净。对于任何好奇的人来说,只是一些额外的思考,并让我有理由自己尝试 measureBlock 功能。 :)

    【讨论】:

    • 需要考虑的事情:如果输入数组有多个条目,其中age == 27
    • 很好,如果是这种情况,并且您想删除所有这些,只需删除中断即可。
    【解决方案4】:

    在这种情况下,您必须遍历每个项目并对每个对象进行手动测试,这可能会很好,具体取决于您处理的数据大小和用例的复杂性。

    或者,考虑将数据存储在 sqlite 数据库中,并在对您可行的情况下对其进行查询。

    【讨论】:

    • 您只需要确保在枚举时不会发生变异。
    猜你喜欢
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多