NSMutableArray подсчитывает вхождения объектов и затем переставляет массив - PullRequest
5 голосов
/ 08 июня 2011

Я искал лучший способ изменить NSMutableArray, который может содержать несколько экземпляров одного и того же объекта. Я работаю также для версий iOS под 4.0, поэтому использование блока - не самый лучший способ.

Вот ситуация:

У меня есть такой массив:

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

Предположим, что object2, object3 и object4, на самом деле являются одинаковыми объектами. И объект1 и объект 7 также. Затем я хотел бы переставить массив так, чтобы сначала появлялось большинство вхождений и так далее. Поэтому массив должен выглядеть следующим образом:

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

Ответы [ 3 ]

6 голосов
/ 08 июня 2011

Есть несколько способов сделать это, один из которых - использовать вспомогательный экземпляр NSCountedSet и функцию, которая использует этот 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;
}

и

NSMutableArray *array = …;

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

[array sortUsingFunction:countedSort context:countedSet];

Редактировать: extremeboredom умело заметил, что если два разных объекта имеют одинаковое количество повторений, то их соответствующие элементы не обязательно являются смежными в результирующем массиве.Это решение следует использовать только в том случае, если нет необходимости, чтобы одни и те же объекты были смежными.

Дальнейшее редактирование: В случае, если вам нужно, чтобы элементы, представляющие один и тот же объект, были смежными, вы можете создать меньший массив только с отдельными элементами, отсортированными по их количеству повторений.Затем создайте еще один массив с элементами, отсортированными по количеству повторов.В зависимости от ваших потребностей, вам может не понадобиться результирующий массив - может быть, только 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];
    }
}
1 голос
/ 16 апреля 2012

То, что вам нужно, это NSBag, от Erica Sadun (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
0 голосов
/ 08 июня 2011

Вы можете управлять этим, используя методы экземпляра isKindOfClass & isMemberOfClass. Так что просто переберите свой массив и продолжайте помещать элементы в новый массив в соответствии с вашими требованиями

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...