NSMutableArray counts the occurrences of objects and then rebuilds the array

I was looking for a better way to modify an NSMutableArray that can contain multiple instances of the same object. I also work for iOS versions under 4.0, so using a block is not the way to go.

Here's the situation:

I have an array like this:

ARRAY = [object1,object2,object3,object4,object5,object6,object7,object8];

Let's say that object2 object3 and object4 are actually the same objects. Both object1 and object 7. Then I would like to rebuild the array so that most cases appear first and so on. So the array should look like this:

[object2, object3, object4, object1, object7, object5, object6, object8];

+5
source share
3 answers

There are several ways to do this, one of which is by using a helper instance NSCountedSetand a function that uses to do this NSCountedSet:

NSInteger countedSort(id obj1, id obj2, void *context) {
    NSCountedSet *countedSet = context;
    NSUInteger obj1Count = [countedSet countForObject:obj1];
    NSUInteger obj2Count = [countedSet countForObject:obj2];

    if (obj1Count > obj2Count) return NSOrderedAscending;
    else if (obj1Count < obj2Count) return NSOrderedDescending;
    return NSOrderedSame;
}

and

NSMutableArray *array = …;

NSCountedSet *countedSet = [[[NSCountedSet alloc] initWithArray:array]
    autorelease];

[array sortUsingFunction:countedSort context:countedSet];

Edit: extremeboredom skillfully remarked that if two different objects have the same repeat counter, then the corresponding elements will not necessarily be adjacent in the resulting array. This solution should only be used if it is not required that the same objects be adjacent.


:, , , , , . , . - , distinctArray, .

NSMutableArray *array = …;
NSCountedSet *countedSet = [[[NSCountedSet alloc] initWithArray:array]
    autorelease];

// Array with distinct elements only, sorted by their repeat count
NSArray *distinctArray = [[countedSet allObjects]
    sortedArrayUsingFunction:countedSort context:countedSet];

// Array with all the elements, where elements representing the same
// object are contiguous
NSMutableArray *sortedArray = [NSMutableArray arrayWithCapacity:[array count]];
for (id object in distinctArray) {
    for (NSUInteger i = 0; i < [countedSet countForObject:object]; i++) {
        [sortedArray addObject:object];
    }
}
+6

, NSBag, (GitHub). :

NSArray *objArray = @[ @"a", @"a", @"b", @"B", @"c", @"cc", @"c"];      
NSBag       *aBag = NSBag.new;

for ( id thing in objArray )     [aBag add:thing];   // fill the bag

for ( id unique in aBag.objects )                    // count'em out
         NSLog(   @"%@,     %i", 
                  unique,   [aBag occurrencesOf:unique] );

:

cc, 1
b, 1
B, 1
c, 2
a, 2
+1

, isKindOfClass isMemberOfClass. .

0

All Articles