1

I know how you can sort an Array by alphabet, but I want to sort my NSMutableArray by the popularity of the objects in it. Imagine an array with the following objects:

  • B
  • A
  • C
  • B
  • B
  • A

I want to sort these objects by popularity and create an array like this:

  • B
  • B
  • B
  • A
  • A
  • C

Is there a good and quick way to do this? Maybe a key for NSSortDescriptor? (couldn't find that)

Thanks

Jelle
  • 284
  • 3
  • 13

4 Answers4

1

Short and to the point, I used the new syntax for array literals for brevity's sake.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        NSArray *ar = @[@"B", @"A", @"C", @"B", @"B", @"A"];
        NSCountedSet *countedSet = [NSCountedSet setWithArray:ar];
        NSArray *sorted = [ar sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            NSInteger diff = [countedSet countForObject:obj1] - [countedSet countForObject:obj2];
            if (diff < 0)
                return NSOrderedDescending;
            else if (diff > 0)
                return NSOrderedAscending;
            else
                return NSOrderedSame;
        }];
        NSLog(@"%@", ar);
        NSLog(@"%@", sorted);
    }
    return 0;
}

Output

2012-05-08 07:25:18.465 Sort[20434:303] (
    B,
    A,
    C,
    B,
    B,
    A
)
2012-05-08 07:25:18.468 Sort[20434:303] (
    B,
    B,
    B,
    A,
    A,
    C
)
Joshua Weinberg
  • 28,598
  • 2
  • 97
  • 90
0
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"theSortKey"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [myArray sortedArrayUsingDescriptors:sortDescriptors];

also see this thread

How to sort an NSMutableArray with custom objects in it?

Community
  • 1
  • 1
Saad
  • 8,857
  • 2
  • 41
  • 51
0

This should work for you.

NSArray *array = [[NSArray alloc] initWithObjects:@"A", @"A", @"B", @"B", @"B", @"C", nil];
NSMutableDictionary *occurenceOfValues = [[NSMutableDictionary alloc] init];
for (id value in array) {
    NSNumber *count = [occurenceOfValues objectForKey:value];
    [occurenceOfValues setValue:[NSNumber numberWithInt:[count intValue] + 1] forKey:value];
}
NSArray *valuesInOrder = [[[occurenceOfValues keysSortedByValueUsingSelector:@selector(compare:)] reverseObjectEnumerator] allObjects];
NSMutableArray *sortedArray = [[NSMutableArray alloc] initWithCapacity:array.count];
for (id value in valuesInOrder) {
    NSNumber *count = [occurenceOfValues objectForKey:value];
    for (int i = 0; i < [count intValue]; i++) {
        [sortedArray addObject:value];
    }
}
NSLog(@"%@", sortedArray);

Console output:

2012-05-08 09:20:15.805 SortArrayPopularity[25206:f803] ( B, B, B, A, A, C )

Ben M
  • 2,405
  • 1
  • 20
  • 19
0

I would use a dictionary which have A,B,C... as the key and set default value to 0

then enumerate the array and increase the count of corresponding key.

finally sort the key array returned by [dict allKeys];

ZeR0
  • 331
  • 3
  • 6