Jak posortować NSMutableArray z niestandardowymi obiektami w nim?

1268

To, co chcę zrobić, wydaje się dość proste, ale nie mogę znaleźć żadnych odpowiedzi w Internecie. Mam jeden NSMutableArrayprzedmiot i powiedzmy, że są to obiekty „Osoby”. Chcę posortować NSMutableArraywedług Person.birthDate, która jest NSDate.

Myślę, że ma to coś wspólnego z tą metodą:

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

W Javie sprawiłbym, że mój obiekt implementował Porównywalny, lub używałbym Collection.sort z wbudowanym komparatorem niestandardowym ... jak do diabła robisz to w Objective-C?

rustyshelf
źródło

Odpowiedzi:

2299

Porównaj metodę

Zaimplementuj metodę porównawczą dla swojego obiektu:

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

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

NSSortDescriptor (lepiej)

lub zwykle nawet lepiej:

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

Możesz łatwo sortować według wielu kluczy, dodając więcej niż jeden do tablicy. Możliwe jest również użycie niestandardowych metod porównawczych. Zajrzyj do dokumentacji .

Bloki (błyszczące!)

Istnieje również możliwość sortowania według bloku od Mac OS X 10.6 i 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];
}];

Wydajność

-compare:I metody blokowe oparte będzie trochę szybciej, na ogół, niż przy użyciu NSSortDescriptorponieważ te ostatnie opiera się na KVC. Podstawową zaletą tej NSSortDescriptormetody jest to, że zapewnia ona sposób definiowania kolejności sortowania przy użyciu danych, a nie kodu, co ułatwia np. Konfigurację, aby użytkownicy mogli sortować NSTableView, klikając wiersz nagłówka.

Georg Schölly
źródło
66
Pierwszy przykład ma błąd: porównujesz zmienną wystąpienia birthDate w jednym obiekcie z samym innym obiektem, a nie jego zmienną birthDate.
Martin Gjaldbaek
90
@Martin: Dzięki! Zabawne, że nikt inny tego nie zauważył, zanim dostałem 75 głosów pozytywnych.
Georg Schölly
76
Ponieważ jest to zaakceptowana odpowiedź, a zatem prawdopodobnie uważana za ostateczną przez większość użytkowników, pomocne może być dodanie trzeciego, opartego na blokach przykładu, aby użytkownicy wiedzieli, że on również istnieje.
jpswain
6
@ orange80: Próbowałem tego. Nie mam już komputera Mac, więc byłoby miło, gdybyś mógł obejrzeć kod.
Georg Schölly,
11
Jeśli masz, NSMutableArraywolę użyć metod sortUsingDescriptors, sortUsingFunctionlub sortUsingSelector. O ile tablica jest zmienna, zwykle nie potrzebuję posortowanej kopii.
Stephan
109

Zobacz NSMutableArraymetodęsortUsingFunction:context:

Konieczne będzie skonfigurowanie funkcji porównania, która pobiera dwa obiekty (typu Person, ponieważ porównujesz dwa Personobiekty) i parametr kontekstu .

Te dwa obiekty są tylko przypadkami Person. Trzeci obiekt to ciąg znaków, np. @ „BirthDate”.

Ta funkcja zwraca NSComparisonResult: Zwraca, NSOrderedAscendingjeśli PersonA.birthDate< PersonB.birthDate. Zwróci, NSOrderedDescendingjeśli PersonA.birthDate> PersonB.birthDate. Wreszcie zwróci, NSOrderedSamejeśli PersonA.birthDate== PersonB.birthDate.

To jest szorstki pseudokod; musisz wyjaśnić, co to znaczy, że jedna data jest „mniejsza”, „większa” lub „równa” z inną datą (np. porównując sekundy od epoki itp.):

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;
}

Jeśli chcesz czegoś bardziej kompaktowego, możesz użyć operatorów trójskładnikowych:

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

Inlining może nieco to przyspieszyć, jeśli często to robisz.

Alex Reynolds
źródło
9
Korzystanie z funkcji sortUsingFunction: context: jest prawdopodobnie najbardziej c-szym sposobem i zdecydowanie najbardziej nieczytelnym.
Georg Schölly,
12
Nie ma w tym nic złego, ale myślę, że są teraz o wiele lepsze alternatywy.
Georg Schölly,
6
Być może, ale nie sądzę, by byłby mniej czytelny dla kogoś ze środowiska Java, który mógłby szukać czegoś podobnego do abstrakcyjnej klasy porównawczej Javy, która implementuje porównywanie (Type obj1, Type obj2).
Alex Reynolds,
5
Wydaje mi się, że niektórzy z was szukają jakiegokolwiek powodu, aby skrytykować tę doskonale idealną odpowiedź, nawet jeśli ta krytyka ma niewiele zalet technicznych. Dziwne.
Alex Reynolds
1
@ Yar: Albo możesz użyć rozwiązania, które podałem w pierwszym akapicie, albo możesz użyć wielu deskryptorów sortowania. sortedArrayUsingDescriptors: przyjmuje tablicę deskryptorów sortowania jako argument.
Georg Schölly,
62

Zrobiłem to w iOS 4 za pomocą bloku. Musiałem rzutować elementy mojej tablicy z id na typ mojej klasy. W tym przypadku była to klasa o nazwie Wynik z właściwością zwaną punktami.

Musisz także zdecydować, co zrobić, jeśli elementy tablicy nie są odpowiedniego typu, w tym przykładzie właśnie wróciłem NSOrderedSame, jednak w moim kodzie pomyślałem o wyjątku.

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: Sortuje w kolejności malejącej.

Chris
źródło
6
Tak naprawdę nie potrzebujesz tam rzutów „(Ocena *)”, możesz po prostu zrobić „Wynik * s1 = obj1;” bo id z radością rzuci na wszystko bez ostrzeżenia kompilatora :-)
jpswain
prawy pomarańczowy 80 downcastingnie wymaga rzutu przed słabą zmienną.
thesummersign
Powinieneś sortować zero i nie zero do góry lub do dołu konsekwentnie, więc domyślnym końcowym return ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
znakiem
heh Chris, wypróbowałem ten kod, odświeżam hv w moim programie .. po raz pierwszy wykonuję poprawną pracę, mam wyjście w kolejności malejącej .. ale kiedy odświeżam. (wykonaj ten sam kod z tymi samymi danymi) to się zmieniło kolejność nie była malejąca. Powiedzmy, że mam 4 obiekty w mojej tablicy, 3 same dane, 1 jest różny.
Nikesh K
Jeśli faktycznie oczekujesz obiektów, które nie należą do klasy „Score”, musisz posortować je nieco ostrożniej. W przeciwnym razie masz sytuację, w której inny == wynik1 <wynik2 == inny, co jest niespójne i może prowadzić do problemów. Możesz zwrócić wartość, która sugeruje sortowanie obiektów score przed wszystkimi innymi obiektami, a wszystkie inne obiekty są sobie równe.
gnasher729
29

Począwszy od iOS 4, możesz także używać bloków do sortowania.

W tym konkretnym przykładzie zakładam, że obiekty w tablicy mają metodę „position”, która zwraca an 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];

Uwaga: tablica „posortowana” zostanie automatycznie wydana.

lewiatan
źródło
26

Próbowałem wszystkich, ale to zadziałało dla mnie. W klasie mam inną klasę o nazwie „ crimeScene” i chcę sortować według właściwości „ crimeScene”.

To działa jak urok:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
Fernando Redondo
źródło
21

W drugiej odpowiedzi Georga Schölly'ego brakuje kroku , ale wtedy działa dobrze.

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

// dodał „s”, ponieważ straciłem czas, gdy kopiowałem i wkleiłem, i nie powiodło się bez „s” w sortedArrayUsingDescriptors

Manuel Spuhler
źródło
Wywołanie metody to tak naprawdę „sortedArrayUsingDescriptors:”, z „s” na końcu.
CIFilter
19
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Dzięki, działa dobrze ...

Hardik Darji
źródło
17

Twoje Personobiekty muszą zaimplementować metodę, powiedzieć, compare:który bierze inny Personobiekt, i powrócić NSComparisonResultzgodnie z relacją między dwoma obiektami.

Wtedy można by nazwać sortedArrayUsingSelector:się @selector(compare:)i powinno się to odbywać.

Istnieją inne sposoby, ale o ile mi wiadomo, nie ma ekwiwalentu kakao Comparableinterfejsu. Używanie sortedArrayUsingSelector:jest prawdopodobnie najbardziej bezbolesnym sposobem na zrobienie tego.

wolna przestrzeń
źródło
9

Bloki iOS 4 cię uratują :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html trochę opisu

Kostiantyn Sokolinskyi
źródło
8

Dla NSMutableArrayużyj sortUsingSelectormetody. Sortuje to miejsce, bez tworzenia nowej instancji.

DenTheMan
źródło
Tylko aktualizacja: ja również szukałem czegoś, co posortuje zmienną tablicę w miejscu, istnieją teraz „sortUsing” równoważne metody dla wszystkich metod „sortedArrayUsing” od iOS 7. Takie jak sortUsingComparator:.
jmathew
7

Możesz użyć do tego celu następującej ogólnej metody. To powinno rozwiązać twój problem.

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];
MD Aslam Ansari
źródło
6

Jeśli tylko sortujesz tablicę NSNumbers, możesz sortować je za pomocą 1 połączenia:

[arrayToSort sortUsingSelector: @selector(compare:)];

Działa to, ponieważ obiekty w tablicy ( NSNumberobiekty) implementują metodę porównywania. To samo możesz zrobić dla NSStringobiektów, a nawet dla tablicy niestandardowych obiektów danych, które implementują metodę porównywania.

Oto przykładowy kod wykorzystujący bloki komparatora. Sortuje tablicę słowników, w których każdy słownik zawiera liczbę w kluczu „sort_key”.

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

Powyższy kod przedstawia pracę polegającą na uzyskaniu wartości całkowitej dla każdego klucza sortowania i porównaniu ich, jako ilustracja tego, jak to zrobić. Ponieważ NSNumberobiekty implementują metodę porównywania, można ją przepisać znacznie prościej:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

lub korpus komparatora może być nawet destylowany do 1 linii:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

Wolę proste instrukcje i wiele zmiennych tymczasowych, ponieważ kod jest łatwiejszy do odczytania i łatwiejszy do debugowania. Kompilator i tak optymalizuje zmienne tymczasowe, więc nie ma przewagi nad wersją „wszystko w jednym wierszu”.

Dinesh_
źródło
5

Stworzyłem małą bibliotekę metod kategorii, o nazwie Linq do ObjectiveC , która ułatwia takie rzeczy. Za pomocą metody sortowania z selektorem klawiszy możesz sortować birthDatew następujący sposób:

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
ColinE
źródło
Powinieneś nazwać to „ LINQ to Objective-C ”.
Peter Mortensen
5

Właśnie wykonałem sortowanie wielopoziomowe na podstawie niestandardowych wymagań.

// posortuj wartości

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

Boobalan
źródło
5

Użyłem sortUsingFunction :: w niektórych moich projektach:

int SortPlays(id a, id b, void* context)
{
    Play* p1 = a;
    Play* p2 = b;
    if (p1.score<p2.score) 
        return NSOrderedDescending;
    else if (p1.score>p2.score) 
        return NSOrderedAscending;
    return NSOrderedSame;
}

...
[validPlays sortUsingFunction:SortPlays context:nil];
roocell
źródło
5

Używasz NSSortDescriptor do sortowania NSMutableArray z niestandardowymi obiektami

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
Arvind Patel
źródło
4
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
Emile Khattar
źródło
po co przekazywać zmienną tablicę, gdy zwracana jest nowa tablica. po co w ogóle tworzyć opakowanie?
vikingosegundo
3

Sortowanie NSMutableArrayjest bardzo proste:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];
Mohit
źródło
2

Sortuj za pomocą NSComparator

Jeśli chcemy sortować obiekty niestandardowe, musimy je podać NSComparator, które służy do porównywania obiektów niestandardowych. Blok zwraca NSComparisonResultwartość oznaczającą kolejność dwóch obiektów. Aby więc posortować, cała tablica NSComparatorjest używana w następujący sposób.

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

Sortowanie za pomocą NSSortDescriptor
Załóżmy na przykład, że mamy tablicę zawierającą instancje klasy niestandardowej, Pracownik ma atrybuty imię, nazwisko i wiek. Poniższy przykład ilustruje sposób tworzenia NSSortDescriptor, którego można użyć do sortowania zawartości tablicy w porządku rosnącym według klucza wieku.

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Sortuj za pomocą niestandardowych porównań
Nazwy są ciągami, a podczas sortowania ciągów, które mają być prezentowane użytkownikowi, zawsze należy używać zlokalizowanego porównania. Często chcesz także wykonać porównanie bez rozróżniania wielkości liter. Oto przykład z (localizedStandardCompare :), aby uporządkować tablicę według nazwiska i imienia.

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

W celu uzyskania informacji i szczegółowej dyskusji zapoznaj się z: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials / object-c / how-to-sort-nsarray-with-custom-objects /

Aamir
źródło
1

Protokoły Swift i programowanie funkcjonalne sprawiają, że bardzo łatwo jest po prostu dostosować swoją klasę do protokołu porównywalnego, wdrożyć metody wymagane przez protokół, a następnie użyć funkcji sortowania (według:) wysokiego rzędu, aby utworzyć posortowaną tablicę bez konieczności użycia nawiasem mówiąc, zmienne tablice.

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)
James Rochabrun
źródło
1

W moim przypadku używam „sortedArrayUsingComparator” do sortowania tablicy. Spójrz na poniższy kod.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

Również moim celem jest

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end
Emre Gürses
źródło
1

Musisz utworzyć sortDescriptor, a następnie możesz posortować tablicę nsmutablearray za pomocą sortDescriptor jak poniżej.

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)
Parth Barot
źródło
1

Użyj tego dla zagnieżdżonych obiektów,

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute jest jednym obiektem i ten obiekt przechowuje obiekt to, że obiekt zawiera wartości ciągu nazwisk.

Sureshkumar Linganathan
źródło
0

Sortuj tablicę w trybie szybkim


Dla Swiftyosoby poniżej jest to bardzo czysta technika, aby osiągnąć cel powyżej na całym świecie. Pozwala mieć przykładową klasę niestandardową, Userktóra ma pewne atrybuty.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

Teraz mamy tablicę, którą musimy posortować na podstawie createdDaterosnącej i / lub malejącej. Dodajmy więc funkcję do porównywania dat.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

Teraz pozwala mieć extensionod Arraydo User. W prostych słowach dodajmy metody tylko dla tych tablic, które zawierają tylko Userobiekty.

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

Zastosowanie dla porządku rosnącego

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Zastosowanie w porządku malejącym

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Wykorzystanie tego samego zamówienia

let sortedArray = someArray.sortUserByDate(.orderedSame)

Powyższa metoda extensionbędzie dostępna tylko wtedy, gdy Arrayjest typu [User]||Array<User>

Syed Qamar Abbas
źródło
0

Wersja szybka: 5.1

Jeśli masz niestandardową strukturę lub klasę i chcesz je dowolnie posortować, powinieneś wywołać sort () za pomocą zamykania końcowego sortującego według określonego pola. Oto przykład z wykorzystaniem tablicy niestandardowych struktur sortujących według określonej właściwości:

    struct User {
        var firstName: String
    }

    var users = [
        User(firstName: "Jemima"),
        User(firstName: "Peter"),
        User(firstName: "David"),
        User(firstName: "Kelly"),
        User(firstName: "Isabella")
    ]

    users.sort {
        $0.firstName < $1.firstName
    }

Jeśli chcesz zwrócić posortowaną tablicę zamiast posortować ją w miejscu, użyj sorted () w następujący sposób:

    let sortedUsers = users.sorted {
        $0.firstName < $1.firstName
    }
sDev
źródło
0
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
manishkumar
źródło
Pytanie dotyczy NSMutableArray, a nie kolekcji Arrays w Swift
Ricardo
-2
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");
Siddhesh Bondre
źródło