Removing duplicates from NSMutableArray

2019-01-06 22:54发布

问题:

I have this problem with removing duplicate objects from an array. I tried these already:

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];
        }
    }
}

But none of the above gave me the right array. The last one was the best, but it still showed duplicate values. Can someone help me with this problem? Thank you very much.

回答1:

Just convert the array to an NSSet and back again. A set can't have duplicates by design.

EDIT:

Note that a set doesn't have a sorting order. Therefore, you can go cheaper and forgo the order, or go for a slightly more expensive operation but keep the order.

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


回答2:

In OS X 10.7 and iOS 5.0 and later:

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


回答3:

If you want to maintain ordering, you could do something like this

@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

This solution has lower computational complexity than most of the others so far suggested; for an array with N elements of which M are unique, it should have worst-case complexity O(N log M), rather than O(N^2). The simpler solutions might be faster for short arrays, however, since this method does have some additional overhead.

Of course, it does rely on your -isEqual: and -hash methods being implemented correctly.



回答4:

How about this category?

@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

You can use it like this:

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


回答5:

I think your problem lies in how you define the equality of your PersonalHistory_artikels objects.

Regardless of the algorithm you use to remove duplicates in an array, make sure you provide adequate -isEqual: and -hash method implementations. See the Apple documentation for those two methods, particularly this paragraph:

If two objects are equal (as determined by the isEqual: method), they must have the same hash value. This last point is particularly important if you define hash in a subclass and intend to put instances of that subclass into a collection.

If a mutable object is added to a collection that uses hash values to determine the object’s position in the collection, the value returned by the hash method of the object must not change while the object is in the collection. Therefore, either the hash method must not rely on any of the object’s internal state information or you must make sure the object’s internal state information does not change while the object is in the collection. Thus, for example, a mutable dictionary can be put in a hash table but you must not change it while it is in there. (Note that it can be difficult to know whether or not a given object is in a collection.)

Hope this helps.



回答6:

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];


回答7:

Best way to remove duplicate element from array:

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


回答8:

No need to create NSSet or anything else. Try this

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


回答9:

For array which contains custom objects:

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

PS: _pSessionArr is the name of mutable array which contains a custom class object which have property named title.