Как отсортировать NSMutableArray, используя sortedArrayUsingDescriptors? - PullRequest
28 голосов
/ 04 декабря 2009

У меня вопрос по сортировке NSMutableArray. Я могу использовать sortedArrayUsingDescriptors: метод для сортировки массива с объектами.

Например, у меня есть NSMutableArray из places, где у меня есть атрибут frequency (значение int), и я хочу отсортировать по убыванию по frequency, но я не знаю, как правильно его использовать.

Что мне поставить в качестве ключа в initWithKey?

Мой объект place содержит:

NSString * name;
NSString * address;
NSString * frequency;
NSString * type;

NSMutableArray * places;

... populate array with objects ...

NSSortDescriptor * sortByFrequency =
   [[[NSSortDescriptor alloc] initWithKey:@"????????" ascending:NO] autorelease];

NSArray * descriptors = [NSArray arrayWithObject:sortByFrequency];
NSArray * sorted = [x sortedArrayUsingDescriptors:descriptors];

Ответы [ 3 ]

111 голосов
/ 04 декабря 2009

Для сортировки вашего массива объектов вы:

  1. setup NSSortDescriptor - использовать имена ваших переменных в качестве ключей для настройки дескриптора для сортировки плюс селектор, который будет выполняться для этих ключей
  2. получить массив дескрипторов, используя NSSortDescriptor, который вы настроили
  3. сортировка массива на основе этих дескрипторов

Вот два примера, один из которых использует NSDictionary и NSString/NSNumber значения, сортирующие по NSNumber, другой - пользовательский класс с сортировкой по двум NSString полям.

Следуйте Сортировка и фильтрация объектов NSArray в темах программирования Какао, чтобы увидеть больше примеров и объяснений.

Пример

Это было сделано на GNUStep, оно должно работать так же на Какао - код точно такой же - я попробую, когда сижу перед моим Mac:

Первый пример с использованием значений NSString и NSNumber с сортировкой по значению NSNumber:

NSString * NAME      = @"name";
NSString * ADDRESS   = @"address";
NSString * FREQUENCY = @"frequency";
NSString * TYPE      = @"type";

NSMutableArray * array = [NSMutableArray array];

NSDictionary * dict;

dict = [NSDictionary dictionaryWithObjectsAndKeys:
            @"Alehandro", NAME, @"Sydney", ADDRESS,
            [NSNumber numberWithInt:100], FREQUENCY,
            @"T", TYPE, nil];
[array addObject:dict];

dict = [NSDictionary dictionaryWithObjectsAndKeys:
            @"Xentro", NAME, @"Melbourne", ADDRESS,
            [NSNumber numberWithInt:50], FREQUENCY,
            @"X", TYPE, nil];
[array addObject:dict];

dict = [NSDictionary dictionaryWithObjectsAndKeys:
            @"John", NAME, @"Perth", ADDRESS,
            [NSNumber numberWithInt:75],
            FREQUENCY, @"A", TYPE, nil];
[array addObject:dict];

dict = [NSDictionary dictionaryWithObjectsAndKeys:
            @"Fjord", NAME, @"Brisbane", ADDRESS,
            [NSNumber numberWithInt:20], FREQUENCY,
            @"B", TYPE, nil];
[array addObject:dict];

Сортировка детали с использованием дескрипторов с полем Frequency, равным NSNumber:

NSSortDescriptor * frequencyDescriptor =
    [[[NSSortDescriptor alloc] initWithKey:FREQUENCY
                                 ascending:YES] autorelease];

id obj;
NSEnumerator * enumerator = [array objectEnumerator];
while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);

NSArray * descriptors =
    [NSArray arrayWithObjects:frequencyDescriptor, nil];
NSArray * sortedArray =
    [array sortedArrayUsingDescriptors:descriptors];

NSLog(@"\nSorted ...");

enumerator = [sortedArray objectEnumerator];
while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);

OUTPUT - отсортировано по полю частоты:

2009-12-04 x[1] {address = Sydney; frequency = 100; name = Alehandro; type = T; }
2009-12-04 x[1] {address = Melbourne; frequency = 50; name = Xentro; type = X; }
2009-12-04 x[1] {address = Perth; frequency = 75; name = John; type = A; }
2009-12-04 x[1] {address = Brisbane; frequency = 20; name = Fjord; type = B; }
2009-12-04 x[1]
Sorted ...
2009-12-04 x[1] {address = Brisbane; frequency = 20; name = Fjord; type = B; }
2009-12-04 x[1] {address = Melbourne; frequency = 50; name = Xentro; type = X; }
2009-12-04 x[1] {address = Perth; frequency = 75; name = John; type = A; }
2009-12-04 x[1] {address = Sydney; frequency = 100; name = Alehandro; type = T; }


Второй пример с пользовательским классом и сортировкой по двум NSString переменным.

Массив для сортировки (см. Класс A внизу):

NSMutableArray * array = [NSMutableArray array];
[array addObject:[[A alloc] initWithFirstName:@"Alehandro"
                                     lastName:@"Xentro"
                                          age:[NSNumber numberWithInt:40]]];
[array addObject:[[A alloc] initWithFirstName:@"John"
                                     lastName:@"Smith"
                                          age:[NSNumber numberWithInt:30]]];
[array addObject:[[A alloc] initWithFirstName:@"John"
                                     lastName:@"Smyth"
                                          age:[NSNumber numberWithInt:25]]];
[array addObject:[[A alloc] initWithFirstName:@"Torro"
                                     lastName:@"Ola"
                                          age:[NSNumber numberWithInt:45]]];
[array addObject:[[A alloc] initWithFirstName:@"Alehandro"
                                     lastName:@"Bento"
                                          age:[NSNumber numberWithInt:41]]];
[array addObject:[[A alloc] initWithFirstName:@"Alehandro"
                                     lastName:@"Axel"
                                          age:[NSNumber numberWithInt:41]]];

Часть сортировки, сортировка по lastName, затем firstName:

NSString * LASTNAME = @"lastName";
NSString * FIRSTNAME = @"firstName";

NSSortDescriptor *lastDescriptor =
    [[[NSSortDescriptor alloc]
        initWithKey:LASTNAME
          ascending:YES
           selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];

NSSortDescriptor *firstDescriptor =
    [[[NSSortDescriptor alloc]
        initWithKey:FIRSTNAME
          ascending:YES
           selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];

NSArray * descriptors =
   [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];
NSArray * sortedArray =
   [array sortedArrayUsingDescriptors:descriptors];

Распечатать результат:

NSLog(@"\nSorted ...");

enumerator = [sortedArray objectEnumerator];
while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);

Результат (до и после сортировки):

2009-12-04 00:52:16.637 x[11375] Alehandro, Xentro, age:40
2009-12-04 00:52:16.644 x[11375] John, Smith, age:30
2009-12-04 00:52:16.644 x[11375] John, Smyth, age:25
2009-12-04 00:52:16.644 x[11375] Torro, Ola, age:45
2009-12-04 00:52:16.645 x[11375] Alehandro, Bento, age:41
2009-12-04 00:52:16.645 x[11375] Alehandro, Axel, age:41
2009-12-04 00:52:16.645 x[11375]
Sorted ...
2009-12-04 00:52:16.645 x[11375] Alehandro, Axel, age:41
2009-12-04 00:52:16.645 x[11375] Alehandro, Bento, age:41
2009-12-04 00:52:16.645 x[11375] Torro, Ola, age:45
2009-12-04 00:52:16.645 x[11375] John, Smith, age:30
2009-12-04 00:52:16.645 x[11375] John, Smyth, age:25
2009-12-04 00:52:16.645 x[11375] Alehandro, Xentro, age:40

Класс A расширяется NSObject - здесь ничего особенного:

#import <Foundation/Foundation.h>

@interface A : NSObject
{
    NSString * firstName;
    NSString * lastName;
    NSNumber * age;
}

- (id)initWithFirstName:(NSString*)aFirstName
               lastName:(NSString*)aLastName
                    age:(NSNumber*)anAge;

-(NSString* )description;
+(NSString*)action;

@end

Реализация:

#import <Foundation/Foundation.h>
#import "A.h"

@implementation A

- (id)init
{
    return [self initWithFirstName:@"N/A"
                          lastName:@"N/A"
                               age:0];
}

- (id)initWithFirstName:(NSString*)aFirstName
               lastName:(NSString*)aLastName
                    age:(NSNumber*)anAge
{
    self = [super init];
    if (!self) return nil;

    firstName = [aFirstName copy];
    lastName = [aLastName copy];
    age = [anAge copy];

    return self;
}

- (void)dealloc
{
    [firstName release];
    [lastName release];
    [age release];
    [super release];
}

- (NSString *) description
{
    return [NSString stringWithFormat: @"%@, %@, age:%@",
                                       firstName, lastName, age];
}
@end
2 голосов
/ 04 декабря 2009

«Ключ» - это метод ваших объектов (элементов вашего массива «x»), который возвращает то, что вы хотите отсортировать. Так что в данном случае вы сказали, что хотите отсортировать по «частоте». Тогда все, что вам нужно сделать, это использовать имя метода, который возвращает частоту, в качестве ключа.

1 голос
/ 04 декабря 2009

Вот как можно отсортировать NSMutableArray:

NSMutableArray *numberSort =[[NSMutableArray alloc] init];

    while ((key = [enumerator nextObject])) {
        //(NSNumber *)integer = [key integerValue];
        [numberSort  addObject:[NSNumber numberWithInt:[key intValue]]];
        // code that uses the returned key 
    }


    NSArray *stringSort = [numberSort sortedArrayUsingSelector:@selector(compare:)];
    enumerator = [stringSort objectEnumerator];
    NSNumber  *intKey;

    NSMutableArray *backToString =[[NSMutableArray alloc] init];

    while ((intKey = [enumerator nextObject])) {
        //(NSNumber *)integer = [key integerValue];
        [backToString  addObject:[intKey stringValue]];
        // code that uses the returned key 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...