Pertanyaan Bagaimana cara mengurutkan NSMutableArray dengan objek kustom di dalamnya?


Apa yang ingin saya lakukan tampaknya cukup sederhana, tetapi saya tidak dapat menemukan jawaban apa pun di web. Saya punya NSMutableArray objek, dan katakanlah mereka adalah objek 'Orang'. Saya ingin mengurutkan NSMutableArray oleh Person.birthDate yang merupakan NSDate.

Saya pikir itu ada hubungannya dengan metode ini:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

Di Java, saya akan membuat objek saya menerapkan Comparable, atau menggunakan Collections.sort dengan pembanding kustom inline ... bagaimana Anda melakukannya di Objective-C?


1173
2018-04-30 06:10


asal


Jawaban:


Bandingkan metode

Entah Anda menerapkan metode perbandingan untuk objek Anda:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (lebih baik)

atau biasanya lebih baik:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

Anda dapat dengan mudah mengurutkan berdasarkan beberapa kunci dengan menambahkan lebih dari satu ke array. Menggunakan metode pembanding khusus juga dimungkinkan. Silahkan lihat dokumentasi.

Blokir (mengkilap!)

Ada juga kemungkinan menyortir dengan blok sejak Mac OS X 10.6 dan iOS 4:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

Kinerja

Itu -compare: dan metode berbasis blok akan sedikit lebih cepat, secara umum, daripada menggunakan NSSortDescriptor karena yang terakhir bergantung pada KVC. Keuntungan utama dari NSSortDescriptor metode ini menyediakan cara untuk menentukan urutan pengurutan Anda menggunakan data, bukan kode, yang membuatnya mudah untuk mis. mengatur segalanya sehingga pengguna dapat mengurutkan NSTableView dengan mengklik pada baris header.


2215
2018-04-30 06:24



Lihat NSMutableArray metode sortUsingFunction:context: 

Anda perlu menyiapkan a membandingkan fungsi yang mengambil dua objek (tipe Person, karena Anda membandingkan dua Person objek) dan a konteks parameter.

Dua objek hanyalah contoh Person. Objek ketiga adalah string, mis. @"tanggal lahir".

Fungsi ini mengembalikan sebuah NSComparisonResult: Ini kembali NSOrderedAscending jika PersonA.birthDate < PersonB.birthDate. Itu akan kembali NSOrderedDescending jika PersonA.birthDate > PersonB.birthDate. Akhirnya, itu akan kembali NSOrderedSame jika PersonA.birthDate == PersonB.birthDate.

Ini adalah pseudocode kasar; Anda akan perlu menyempurnakan apa artinya untuk satu tanggal menjadi "kurang", "lebih" atau "sama" dengan tanggal lain (seperti membandingkan detik-sejak-zaman dll):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

Jika Anda menginginkan sesuatu yang lebih ringkas, Anda dapat menggunakan operator terner:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

Inlining mungkin bisa mempercepat ini sedikit, jika Anda melakukan ini banyak.


103
2018-03-24 22:15



Saya melakukan ini di iOS 4 menggunakan blok. Harus membuang elemen-elemen array saya dari id ke tipe kelas saya. Dalam hal ini adalah kelas yang disebut Skor dengan properti yang disebut poin.

Juga Anda perlu memutuskan apa yang harus dilakukan jika elemen array Anda bukan tipe yang tepat, untuk contoh ini saya baru saja kembali NSOrderedSameNamun dalam kode saya, saya meskipun pengecualian.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS: Ini sortir dalam urutan menurun.


58
2018-03-16 18:46



Mulai di iOS 4 Anda juga dapat menggunakan blok untuk menyortir.

Untuk contoh khusus ini saya mengasumsikan bahwa objek dalam array Anda memiliki metode 'posisi', yang mengembalikan sebuah NSInteger.

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

Catatan: array "disortir" akan di-autoreleased.


28
2017-11-22 10:51



Saya mencoba semua, tetapi ini berhasil bagi saya. Di kelas saya memiliki kelas lain bernama "crimeScene", dan ingin mengurutkan berdasarkan milik"crimeScene".

Ini bekerja seperti pesona:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

24
2018-05-06 16:25



Ada langkah yang hilang Jawaban kedua Georg Schölly, tetapi berfungsi dengan baik.

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptor:sortDescriptors];

19
2018-03-30 05:54



NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Terima kasih, ini berfungsi dengan baik ...


18
2018-04-30 06:20