如果您要制作过滤掉某些项目的数组副本,则制作一个新的可变数组,迭代原始数组并动态添加到副本中,正如其他人对此答案所建议的那样。但是您的问题是从现有(可能是可变的)数组中删除。
在迭代时,您可以构建一个要删除的对象数组,然后再删除它们:
NSMutableArray *thePeople = ...
NSString *hairColorToMatch = ...
NSMutableArray *matchingObjects = [NSMutableArray array];
for (People *person in thePeople) {
if (person.hairColor isEqualToString:hairColorToMatch])
[matchingObjects addObject:person];
[thePeople removeObjects:matchingObjects];
但这会创建一个临时数组,您可能认为这很浪费,更重要的是,很难看到removeObjects: 非常有效。另外,有人提到了一些关于具有重复项的数组,这在这种情况下应该可以工作,但不是最好的,每个重复项也在临时数组中,并且在removeObjects: 中进行冗余匹配。
可以改为按索引进行迭代并在进行时删除,但这会使循环逻辑相当尴尬。相反,我会收集索引集中的索引,然后再次删除:
NSMutableIndexSet *matchingIndexes = [NSMutableIndexSet indexSet];
for (NSUInteger n = thePeople.count, i = 0; i < n; ++i) {
People *person = thePeople[i];
if ([person.hairColor isEqualToString:hairColorToMatch])
[matchingIndexes addIndex:i];
}
[thePeople removeObjectsAtIndexes:matchingIndexes];
我相信索引集的开销非常低,因此这几乎与您将获得的效率一样高,而且很难搞砸。像这样在最后批量删除的另一件事是,Apple 可能已将 removeObjectsAtIndexes: 优化为优于 removeObjectAtIndex: 的序列。因此,即使有创建索引集数据结构的开销,这也可能会在迭代时快速删除。如果数组有重复,这个也很好用。
如果相反,您确实在制作过滤副本,那么我认为您可以使用一些 KVC 集合运算符(我最近正在阅读这些内容,您可以根据 NSHipster 和 @ 做一些疯狂的事情987654322@)。显然没有,但很接近,需要在这个有点罗嗦的行中使用 KVC 和 NSPredicate:
NSArray *subsetOfPeople = [allPeople filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:@"SELF.hairColor != %@", hairColorToMatch]];
请继续在 NSArray 上创建一个类别,以使您的代码更简洁,filterWithFormat: 或其他内容。
(全部未经测试,直接输入SO)