Wie sortiere ich ein NSMutableArray mit benutzerdefinierten Objekten?

1268

Was ich tun möchte, scheint ziemlich einfach zu sein, aber ich kann im Web keine Antworten finden. Ich habe ein NSMutableArrayObjekt, und sagen wir, es handelt sich um "Personen" -Objekte. Ich möchte das NSMutableArraynach Person.birthDate sortieren, das ein ist NSDate.

Ich denke, das hat etwas mit dieser Methode zu tun:

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

In Java würde ich mein Objekt Comparable implementieren lassen oder Collections.sort mit einem benutzerdefinierten Inline-Komparator verwenden ... wie um alles in der Welt machen Sie das in Objective-C?

rostig
quelle

Antworten:

2299

Methode vergleichen

Entweder implementieren Sie eine Vergleichsmethode für Ihr Objekt:

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

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

NSSortDescriptor (besser)

oder normalerweise noch besser:

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

Sie können einfach nach mehreren Schlüsseln sortieren, indem Sie dem Array mehrere hinzufügen. Die Verwendung von benutzerdefinierten Komparatormethoden ist ebenfalls möglich. Schauen Sie sich die Dokumentation an .

Blöcke (glänzend!)

Seit Mac OS X 10.6 und iOS 4 besteht auch die Möglichkeit, mit einem Block zu sortieren:

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

Performance

Die -compare:und blockbasierten Methoden sind im Allgemeinen viel schneller als die Verwendung, NSSortDescriptorda letztere auf KVC beruht. Der Hauptvorteil der NSSortDescriptorMethode besteht darin, dass sie eine Möglichkeit bietet, Ihre Sortierreihenfolge mithilfe von Daten anstelle von Code zu definieren. Dies macht es einfach, z. B. Dinge so einzurichten, dass Benutzer eine sortieren können, NSTableViewindem sie auf die Kopfzeile klicken.

Georg Schölly
quelle
66
Das erste Beispiel hat einen Fehler: Sie vergleichen die Instanzvariable "BirthDate" in einem Objekt mit dem anderen Objekt selbst und nicht mit der Variablen "BirthDate".
Martin Gjaldbaek
90
@ Martin: Danke! Komisch, dass es sonst niemand bemerkt hat, bevor ich 75 Upvotes dafür bekommen habe.
Georg Schölly
76
Da dies die akzeptierte Antwort ist und daher von den meisten Benutzern wahrscheinlich als endgültig angesehen wird, kann es hilfreich sein, ein drittes blockbasiertes Beispiel hinzuzufügen, damit die Benutzer wissen, dass es auch existiert.
jpswain
6
@ orange80: Das habe ich versucht. Ich besitze keinen Mac mehr, also wäre es schön, wenn Sie sich den Code ansehen könnten.
Georg Schölly
11
Wenn Sie eine haben, NSMutableArraybevorzuge ich die Methoden sortUsingDescriptors, sortUsingFunctionoder sortUsingSelector. Soweit das Array veränderbar ist, benötige ich normalerweise keine sortierte Kopie.
Stephan
109

Siehe die NSMutableArrayMethodesortUsingFunction:context:

Sie müssen eine Vergleichsfunktion einrichten, die zwei Objekte (vom Typ Person, da Sie zwei PersonObjekte vergleichen) und einen Kontextparameter verwendet .

Die beiden Objekte sind nur Instanzen von Person. Das dritte Objekt ist eine Zeichenfolge, z. B. @ "BirthDate".

Diese Funktion gibt Folgendes zurück NSComparisonResult: Sie gibt NSOrderedAscendingif PersonA.birthDate<zurück PersonB.birthDate. Es wird zurückgegeben, NSOrderedDescendingwenn PersonA.birthDate> PersonB.birthDate. Schließlich wird NSOrderedSameif PersonA.birthDate== zurückgegeben PersonB.birthDate.

Dies ist ein grober Pseudocode. Sie müssen genau festlegen, was es bedeutet, dass ein Datum "weniger", "mehr" oder "gleich" zu einem anderen Datum ist (z. B. Vergleich der Sekunden seit der Epoche usw.):

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

Wenn Sie etwas Kompakteres wünschen, können Sie ternäre Operatoren verwenden:

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

Inlining könnte dies vielleicht etwas beschleunigen, wenn Sie dies viel tun.

Alex Reynolds
quelle
9
Die Verwendung von sortUsingFunction: context: ist wahrscheinlich der am besten geeignete und definitiv der am wenigsten lesbare.
Georg Schölly
12
Es ist nichts wirklich falsch daran, aber ich denke, es gibt jetzt viel bessere Alternativen.
Georg Schölly
6
Vielleicht, aber ich denke nicht, dass es für jemanden mit Java-Hintergrund weniger lesbar wäre, der nach etwas ähnlichem wie Javas abstrakter Comparator-Klasse sucht, die compare implementiert (Typ obj1, Typ obj2).
Alex Reynolds
5
Ich habe das Gefühl, dass einige von Ihnen nach einem Grund suchen, diese vollkommen gute Antwort zu kritisieren, auch wenn diese Kritik nur einen sehr geringen technischen Wert hat. Seltsam.
Alex Reynolds
1
@Yar: Entweder können Sie die Lösung verwenden, die ich im ersten Absatz bereitgestellt habe, oder Sie verwenden mehrere Sortierdeskriptoren. sortiertArrayUsingDescriptors: Nimmt ein Array von Sortierdeskriptoren als Argument.
Georg Schölly
62

Ich habe dies in iOS 4 mit einem Block gemacht. Musste die Elemente meines Arrays von id in meinen Klassentyp umwandeln. In diesem Fall handelte es sich um eine Klasse namens Score mit einer Eigenschaft namens points.

Außerdem müssen Sie entscheiden, was zu tun ist, wenn die Elemente Ihres Arrays nicht vom richtigen Typ sind. In diesem Beispiel habe ich gerade zurückgegeben NSOrderedSame, aber in meinem Code habe ich eine Ausnahme.

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: Dies ist in absteigender Reihenfolge sortiert.

Chris
quelle
6
Sie brauchen die "(Score *)" - Casts dort nicht wirklich, Sie können einfach "Score * s1 = obj1;" weil id gerne ohne Vorwarnung des Compilers auf irgendetwas
umgestellt wird
rechts orange80 downcastingerfordert keine Umwandlung vor der schwachen Variablen.
Sommerzeichen
Sie sollten Null gegen Nicht-Null konsistent nach oben oder unten sortieren, damit die Standardergebnisrendite return ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
lautet
heh Chris, ich habe diesen Code ausprobiert, ich habe eine Aktualisierung in meinem Programm. Zum ersten Mal habe ich einen korrekten Job ausgeführt und eine Ausgabe in absteigender Reihenfolge erhalten. Aber als ich aktualisiere (denselben Code mit denselben Daten ausführen), hat sich dieser geändert Die Reihenfolge war nicht absteigend. Angenommen, ich habe 4 Objekte in meinem Array, 3 hv gleiche Daten, 1 ist unterschiedlich.
Nikesh K
Wenn Sie tatsächlich Objekte erwarten, die nicht zur Klasse "Score" gehören, müssen Sie sie etwas sorgfältiger sortieren. Andernfalls haben Sie eine Situation, in der other == score1 <score2 == other inkonsistent ist und zu Problemen führen kann. Sie können einen Wert zurückgeben, der impliziert, dass Score-Objekte vor allen anderen Objekten sortiert werden und alle anderen Objekte gleich sortiert werden.
Gnasher729
29

Ab iOS 4 können Sie auch Blöcke zum Sortieren verwenden.

In diesem Beispiel gehe ich davon aus, dass die Objekte in Ihrem Array eine 'position'-Methode haben, die eine zurückgibt 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];

Hinweis: Das "sortierte" Array wird automatisch freigegeben.

Leviathan
quelle
26

Ich habe alles versucht, aber das hat bei mir funktioniert. In einer Klasse habe ich eine andere Klasse mit dem Namen " crimeScene" und möchte nach der Eigenschaft " crimeScene" sortieren .

Das funktioniert wie ein Zauber:

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

In Georg Schöllys zweiter Antwort fehlt ein Schritt , aber dann funktioniert es gut.

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

// fügte das 's' hinzu, weil beim Kopieren und Einfügen Zeit verschwendet wurde und es ohne das 's' in sortiertenArrayUsingDescriptors fehlschlug

Manuel Spuhler
quelle
Der Methodenaufruf lautet tatsächlich "sortedArrayUsingDescriptors:", mit einem 's' am Ende.
CIFilter
19
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Danke, es funktioniert gut ...

Hardik Darji
quelle
17

Ihre PersonObjekte müssen eine Methode implementieren, beispielsweise ein compare:anderes PersonObjekt, und NSComparisonResultentsprechend der Beziehung zwischen den beiden Objekten zurückkehren.

Dann würde rufen Sie sortedArrayUsingSelector:mit @selector(compare:)und es sollte getan werden.

Es gibt andere Möglichkeiten, aber soweit ich weiß, gibt es kein Kakao-Äquiv der ComparableSchnittstelle. Verwenden sortedArrayUsingSelector:ist wahrscheinlich der schmerzloseste Weg, dies zu tun.

Freiraum
quelle
9

iOS 4 Blöcke werden dich retten :)

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 eine kurze Beschreibung

Kostiantyn Sokolinskyi
quelle
8

Für NSMutableArrayverwenden Sie das sortUsingSelectorVerfahren. Es sortiert es an einem Ort, ohne eine neue Instanz zu erstellen.

DenTheMan
quelle
Nur ein Update: Auch ich habe nach etwas gesucht, das das veränderbare Array sortiert hat. Es gibt jetzt "sortUsing" -äquivalente Methoden für alle "sortedArrayUsing" -Methoden ab iOS 7. Wie z sortUsingComparator:.
Jmathew
7

Sie können die folgende generische Methode für Ihren Zweck verwenden. Es sollte Ihr Problem lösen.

//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
quelle
6

Wenn Sie nur ein Array von NSNumberssortieren, können Sie sie mit einem Aufruf sortieren:

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

Dies funktioniert, weil die Objekte im Array ( NSNumberObjekte) die Vergleichsmethode implementieren. Sie können dasselbe für NSStringObjekte oder sogar für ein Array von benutzerdefinierten Datenobjekten tun , die eine Vergleichsmethode implementieren.

Hier ist ein Beispielcode mit Komparatorblöcken. Es sortiert ein Array von Wörterbüchern, wobei jedes Wörterbuch eine Zahl in einem Schlüssel "sort_key" enthält.

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

Der obige Code geht durch die Arbeit, einen ganzzahligen Wert für jeden Sortierschlüssel zu erhalten und diese zu vergleichen, um zu veranschaulichen, wie dies zu tun ist. Da NSNumberObjekte eine Vergleichsmethode implementieren, könnte sie viel einfacher umgeschrieben werden:

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

oder der Körper des Komparators könnte sogar auf 1 Zeile herunterdestilliert werden:

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

Ich bevorzuge eher einfache Anweisungen und viele temporäre Variablen, da der Code leichter zu lesen und leichter zu debuggen ist. Der Compiler optimiert die temporären Variablen ohnehin, sodass die All-in-One-Line-Version keinen Vorteil bietet.

Dinesh_
quelle
5

Ich habe eine kleine Bibliothek von Kategoriemethoden namens Linq to ObjectiveC erstellt , die diese Art von Dingen einfacher macht. Mit der Sortiermethode mit einem Schlüsselwähler können Sie birthDatewie folgt sortieren :

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
ColinE
quelle
Sie sollten es " LINQ to Objective-C " nennen.
Peter Mortensen
5

Ich habe gerade eine mehrstufige Sortierung basierend auf benutzerdefinierten Anforderungen durchgeführt.

// sortiere die Werte

    [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
quelle
5

Ich habe sortUsingFunction :: in einigen meiner Projekte verwendet:

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
quelle
5

Sie verwenden NSSortDescriptor, um ein NSMutableArray mit benutzerdefinierten Objekten zu sortieren

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
Arvind Patel
quelle
4
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
Emile Khattar
quelle
Warum sollte ein veränderbares Array übergeben werden, wenn ein neues Array zurückgegeben wird? Warum überhaupt einen Wrapper erstellen?
Vikingosegundo
3

Das Sortieren NSMutableArrayist sehr einfach:

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
quelle
2

Sortieren mit NSComparator

Wenn wir benutzerdefinierte Objekte sortieren möchten, müssen wir diese bereitstellen NSComparator, um benutzerdefinierte Objekte zu vergleichen. Der Block gibt einen NSComparisonResultWert zurück, der die Reihenfolge der beiden Objekte angibt. Um das gesamte Array zu sortieren, NSComparatorwird es folgendermaßen verwendet.

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

Sortieren mit NSSortDescriptor
Nehmen wir als Beispiel an, dass wir ein Array haben, das Instanzen einer benutzerdefinierten Klasse enthält. Der Mitarbeiter hat die Attribute Vorname, Nachname und Alter. Das folgende Beispiel zeigt, wie ein NSSortDescriptor erstellt wird, mit dem der Array-Inhalt in aufsteigender Reihenfolge nach dem Altersschlüssel sortiert werden kann.

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

Sortieren mit benutzerdefinierten Vergleichen
Namen sind Zeichenfolgen. Wenn Sie Zeichenfolgen sortieren, die dem Benutzer angezeigt werden sollen, sollten Sie immer einen lokalisierten Vergleich verwenden. Oft möchten Sie auch einen Vergleich ohne Berücksichtigung der Groß- und Kleinschreibung durchführen. Hier kommt ein Beispiel mit (localizedStandardCompare :), um das Array nach Nach- und Vornamen zu sortieren.

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

Referenz und ausführliche Diskussion finden Sie unter: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials / objectiv-c / wie-nsarray-mit-benutzerdefinierten-Objekten sortiert wird /

Aamir
quelle
1

Die Protokolle und die funktionale Programmierung von Swift machen es sehr einfach, dass Sie Ihre Klasse nur an das Comparable-Protokoll anpassen, die vom Protokoll geforderten Methoden implementieren und dann die sortierte (nach :) Funktion hoher Ordnung verwenden müssen, um ein sortiertes Array zu erstellen, ohne es verwenden zu müssen veränderbare Arrays übrigens.

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
quelle
1

In meinem Fall verwende ich "sortedArrayUsingComparator", um ein Array zu sortieren. Schauen Sie sich den folgenden Code an.

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

Auch mein Objekt ist,

@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
quelle
1

Sie müssen sortDescriptor erstellen und können dann das nsmutablearray mithilfe von sortDescriptor wie unten sortieren.

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

Verwenden Sie diese Option für verschachtelte Objekte.

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

lastRoute ist ein Objekt und dieses Objekt enthält das Objekt to, das Objekt object enthält die Zeichenfolgenwerte für den Nachnamen.

Sureshkumar Linganathan
quelle
0

Array in Swift sortieren


Für SwiftyPerson unten ist eine sehr saubere Technik, um über dem Ziel für global zu erreichen. Lassen Sie uns eine benutzerdefinierte Beispielklasse haben, von Userder einige Attribute haben.

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

Jetzt haben wir ein Array, das wir createdDateentweder aufsteigend oder / oder absteigend sortieren müssen . Fügen wir also eine Funktion für den Datumsvergleich hinzu.

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

Jetzt haben wir ein extensionvon Arrayfür User. In einfachen Worten können Sie einige Methoden nur für diejenigen Arrays hinzufügen, die nur UserObjekte enthalten.

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

Verwendung für aufsteigende Reihenfolge

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Verwendung für absteigende Reihenfolge

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Verwendung bei gleicher Bestellung

let sortedArray = someArray.sortUserByDate(.orderedSame)

Die obige Methode in extensionist nur verfügbar, wenn die Arrayvom Typ [User]|| istArray<User>

Syed Qamar Abbas
quelle
0

Schnelle Version: 5.1

Wenn Sie eine benutzerdefinierte Struktur oder Klasse haben und diese willkürlich sortieren möchten, sollten Sie sort () mit einem abschließenden Abschluss aufrufen, der nach einem von Ihnen angegebenen Feld sortiert. Hier ist ein Beispiel mit einem Array von benutzerdefinierten Strukturen, die nach einer bestimmten Eigenschaft sortieren:

    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
    }

Wenn Sie ein sortiertes Array zurückgeben möchten, anstatt es an Ort und Stelle zu sortieren, verwenden Sie sorted () wie folgt:

    let sortedUsers = users.sorted {
        $0.firstName < $1.firstName
    }
sDev
quelle
0
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
manishkumar
quelle
Die Frage bezieht sich auf NSMutableArray, nicht auf die Arrays-Sammlung in 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
quelle