从NSMutableArray中删除重复项

时间:2011-05-12 13:20:16

标签: objective-c cocoa-touch cocoa nsmutablearray

我从数组中删除重复的对象时遇到此问题。 我已经尝试了这些:

noDuplicates = _personalHistory.personalHistory;

for (int i=[noDuplicates count]-1; i>0; i--) {
    if ([noDuplicates indexOfObject: [noDuplicates objectAtIndex: i]]<i)
        [noDuplicates removeObjectAtIndex: i];
}


for (PersonalHistory_artikels *e in _personalHistory.personalHistory) {
    if (![noDuplicates containsObject:e]) {
        NSLog(@"Dubplicates");
        [noDuplicates addObject:e];
    }
}


for (i=0; i<_personalHistory.personalHistory.count; i++) {
    PersonalHistory_artikels *test = [_personalHistory.personalHistory objectAtIndex:i];
    for (j=0; j<_personalHistory.personalHistory.count; j++) {
        PersonalHistory_artikels *test2 = [_personalHistory.personalHistory objectAtIndex:j];
        if (! [test.nieuwsTITLE_personal isEqual:test2.nieuwsTITLE_personal]) {
            NSLog(@"Add test = %@", test.nieuwsTITLE_personal);
            [noDuplicates addObject:test];
        }
    }
}

但上面没有一个给我正确的阵列。最后一个是最好的,但它仍显示重复值。有人可以帮我解决这个问题吗? 非常感谢你。

9 个答案:

答案 0 :(得分:36)

只需将数组转换为NSSet然后再将其转换回来。一个集合不能设计重复。

编辑:

请注意,集合没有排序顺序。因此,您可以更便宜并放弃订单,或者进行稍微昂贵的操作但保留订单。

NSArray *hasDuplicates = /* (...) */;
NSArray *noDuplicates = [[NSSet setWithArray: hasDuplicates] allObjects];

答案 1 :(得分:17)

在OS X 10.7和iOS 5.0及更高版本中:

newArray = [[NSOrderedSet orderedSetWithArray:oldArray] array];

答案 2 :(得分:6)

如果你想维持订购,你可以做这样的事情

@interface NSArray (OrderedDuplicateElimination)

- (NSArray *)arrayByEliminatingDuplicatesMaintainingOrder
{
  NSMutableSet *addedObjects = [NSMutableSet set];
  NSMutableArray *result = [NSMutableArray array];

  for (id obj in self) {
    if (![addedObjects containsObject:obj]) {
      [result addObject:obj];
      [addedObjects addObject:obj];
    }
  }

  return result;
}

@end

该解决方案的计算复杂度低于目前为止提出的大多数其他解决方案;对于具有M个唯一的N个元素的数组,它应该具有最坏情况复杂度O(N log M),而不是O(N ^ 2)。然而,对于短数组,更简单的解决方案可能更快,因为这种方法确实有一些额外的开销。

当然,它确实依赖于您正确实施的-isEqual:-hash方法。

答案 3 :(得分:3)

这个类别怎么样?

@implementation NSArray (Unique)

- (NSArray*) arrayByDroppingDuplicates
{
    NSMutableArray *tmp = [NSMutableArray array];
    for (id item in self)
        if (![tmp containsObject:item])
            [tmp addObject:item];
    return [NSArray arrayWithArray:tmp];
}

@end

你可以像这样使用它:

NSArray *items = [NSArray arrayWithObjects:@"foo", @"bar", @"foo", nil];
NSArray *unique = [items arrayByDroppingDuplicates]; // [@"foo", @"bar"]

答案 4 :(得分:2)

我认为您的问题在于如何定义PersonalHistory_artikels对象的相等性。

无论您使用哪种算法删除数组中的重复项,请确保提供足够的-isEqual:-hash方法实现。有关这两种方法,请参阅Apple documentation,特别是本段:

  

如果两个对象相等(由isEqual:方法确定),则它们必须具有相同的哈希值。如果在子类中定义哈希并打算将该子类的实例放入集合中,则最后一点尤为重要。

     

如果将可变对象添加到使用哈希值来确定对象在集合中的位置的集合中,则对象的哈希方法返回的值在对象位于集合中时不得更改。因此,散列方法必须不依赖于任何对象的内部状态信息,或者必须确保在对象位于集合中时对象的内部状态信息不会更改。因此,例如,可变字典可以放在哈希表中,但是当它在那里时你不能改变它。 (请注意,可能很难知道给定对象是否在集合中。)

希望这有帮助。

答案 5 :(得分:1)

NSArray *copy = [mutableArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
    if ([mutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
        [mutableArray removeObjectAtIndex:index];
    }
    index--;
}
[copy release];

答案 6 :(得分:1)

从数组中删除重复元素的最佳方法:

uniquearray = [[NSSet setWithArray:yourarray] allObjects];

答案 7 :(得分:0)

无需创建NSSet或其他任何内容。 试试这个

noDuplicates = [orgArray valueForKeyPath:@"@distinctUnionOfObjects.self"];

答案 8 :(得分:0)

对于包含自定义对象的数组:

    NSArray *arrUnique = [_pSessionArr valueForKeyPath:@"@distinctUnionOfObjects.self.title"];
    [_pSessionArr removeObjectsInRange:NSMakeRange(arrUnique.count, _pSessionArr.count-arrUnique.count )];

PS:_pSessionArr是可变数组的名称,它包含一个名为title的属性的自定义类对象。