我有一个包含自定义对象的数组。每个数组项都有一个名为“name”的字段。现在我想根据这个名称值删除重复的条目。
我该如何实现这个目标?
我有一个包含自定义对象的数组。每个数组项都有一个名为“name”的字段。现在我想根据这个名称值删除重复的条目。
我该如何实现这个目标?
我不知道框架中是否有标准的方法可以做到这一点。因此,您需要在代码中完成它。类似这样的内容应该是可行的:
NSArray* originalArray = ... // However you fetch it
NSMutableSet* existingNames = [NSMutableSet set];
NSMutableArray* filteredArray = [NSMutableArray array];
for (id object in originalArray) {
if (![existingNames containsObject:[object name]]) {
[existingNames addObject:[object name]];
[filteredArray addObject:object];
}
}
你可能需要自己编写这个过滤方法:
@interface NSArray (CustomFiltering)
@end
@implementation NSArray (CustomFiltering)
- (NSArray *) filterObjectsByKey:(NSString *) key {
NSMutableSet *tempValues = [[NSMutableSet alloc] init];
NSMutableArray *ret = [NSMutableArray array];
for(id obj in self) {
if(! [tempValues containsObject:[obj valueForKey:key]]) {
[tempValues addObject:[obj valueForKey:key]];
[ret addObject:obj];
}
}
[tempValues release];
return ret;
}
@end
NSMutableSet
而不是 NSMutableArray
进行查找,哈希查找的性能提升要比线性查找好得多。 - PeyloW[NSMutableSet set]
而不是alloc/init+release。其次,你应该使用-member:
而不是-containsObject:
。-containsObject:
的文档说明返回给定对象是否存在于集合中,但没有定义“存在”的含义。可以合理地假设它使用指针相等性。-member:
的文档说明使用-isEqual:
,这才是你实际想要测试的内容。 - Lily Ballardalloc/init
,因为我不希望该集合一直停留在自动释放池中。实际上,代码只需要在循环执行时该集合存在,因此这种方式可以尽早地将其从内存中释放。 - Jacob Relkin我知道这是一个老问题,但这里有另一种可能性,具体取决于您的需求。
苹果公司确实提供了一种方法-键值编码集合运算符。
对象运算符允许您对集合进行操作。在这种情况下,您需要:
@distinctUnionOfObjects
@distinctUnionOfObjects运算符返回一个数组,其中包含右侧运算符后面指定的属性中不同的对象。
NSArray *distinctArray = [arrayWithDuplicates
valueForKeyPath:@"@distinctUnionOfObjects.name"];
然而,在您的情况下,您想要整个对象。因此,您需要执行两个操作:
1)改用@distinctUnionOfArrays
。例如,如果您从其他集合获得这些自定义对象,请使用@distinctUnionOfArray.myCollectionOfObjects
2)在这些对象上实现isEqual:
以返回它们的.name是否相等。
我可能因此会受到批评...
你可以将数组转换为字典。不确定这有多有效率,这取决于实现和比较调用,但它确实使用了哈希映射。
//Get unique entries
NSArray *myArray = @[@"Hello", @"World", @"Hello"];
NSDictionary *uniq = [NSDictionary dictionaryWithObjects:myArray forKeys:myArray];
NSLog(@"%@", uniq.allKeys);
这是一行非常简单的代码
NSArray *duplicateList = ...
NSArray *withoutDUP1 = [[NSSet setWithArray:duplicateList] allObjects];
NSArray *withoutDUP2 = [[NSOrderedSet orderedSetWithArray:duplicateList] array];
NSArray * newArray =
[[NSOrderedSet orderedSetWithArray:oldArray] array]; **// iOS 5.0 and later**
实现isEqual方法使你的对象可以进行比较:
@interface SomeObject (Equality)
@end
@implementation SomeObject (Equality)
- (BOOL)isEqual:(SomeObject*)other
{
return self.hash == other.hash;
}
- (NSUInteger)hash
{
return self.name;///your case
}
@end
使用方法:
- (NSArray*)distinctObjectsFromArray:(NSArray*)array
{
return [array valueForKeyPath:@"@distinctUnionOfObjects.self"];
}