1324 Stimmen

Wie kann ich ein NSMutableArray mit benutzerdefinierten Objekten darin sortieren?

Was ich tun möchte, scheint ziemlich einfach zu sein, aber ich kann keine Antworten im Internet finden. Ich habe eine NSMutableArray von Objekten, und sagen wir, es sind 'Person'-Objekte. Ich möchte die NSMutableArray durch Person.birthDate, das eine NSDate .

Ich glaube, es hat etwas mit dieser Methode zu tun:

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

In Java würde ich dafür sorgen, dass mein Objekt Comparable implementiert, oder Collections.sort mit einem benutzerdefinierten Inline-Vergleicher verwenden... wie um alles in der Welt machen Sie das in Objective-C?

2348voto

Georg Schölly Punkte 120083

Methode vergleichen

Entweder Sie implementieren eine compare-Methode für Ihr Objekt:

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

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

NSSortDescriptor (besser)

oder in der Regel sogar besser:

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

Sie können leicht nach mehreren Schlüsseln sortieren, indem Sie dem Array mehr als einen hinzufügen. Die Verwendung eigener Komparator-Methoden ist ebenfalls möglich. Werfen Sie einen Blick auf die Dokumentation .

Blöcke (glänzend!)

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

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

Leistung

Le site -compare: und blockbasierte Methoden sind im Allgemeinen um einiges schneller als die Verwendung von NSSortDescriptor da letztere sich auf KVC stützt. Der Hauptvorteil der NSSortDescriptor Methode ist, dass sie eine Möglichkeit bietet, die Sortierreihenfolge anhand von Daten und nicht anhand von Code zu definieren, was es einfach macht, z. B. eine Sortierreihenfolge für die Benutzer einzurichten. NSTableView indem Sie auf die Kopfzeile klicken.

113voto

Alex Reynolds Punkte 93906

Ver el NSMutableArray Methode sortUsingFunction:context:

Sie müssen eine vergleichen Funktion, die zwei Objekte (vom Typ Person da Sie zwei unterschiedliche Person Objekte) und ein Kontext Parameter.

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

Diese Funktion gibt ein NSComparisonResult : Sie liefert NSOrderedAscending si PersonA.birthDate < PersonB.birthDate . Es wird zurückgegeben NSOrderedDescending si PersonA.birthDate > PersonB.birthDate . Schließlich wird sie zurückkehren NSOrderedSame si PersonA.birthDate == PersonB.birthDate .

Dies ist ein grober Pseudocode; Sie müssen herausfinden, was es bedeutet, wenn ein Datum "weniger", "mehr" oder "gleich" zu einem anderen Datum ist (z. B. Vergleich von Sekunden seit 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 wollen, 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;
}

Das Inlining könnte dies vielleicht ein wenig beschleunigen, wenn Sie dies häufig tun.

66voto

Chris Punkte 996

Ich habe das in iOS 4 mit einem Block gemacht. Musste die Elemente meines Arrays von id auf meinen Klassentyp übertragen. In diesem Fall war es eine Klasse namens Score mit einer Eigenschaft namens Punkte.

Sie müssen auch entscheiden, was zu tun ist, wenn die Elemente Ihres Arrays nicht vom richtigen Typ sind. Für dieses Beispiel habe ich einfach NSOrderedSame In meinem Code habe ich jedoch eine Ausnahme gemacht.

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: Die Sortierung erfolgt in absteigender Reihenfolge.

31voto

Fernando Redondo Punkte 1505

Ich habe alle ausprobiert, aber das hat bei mir funktioniert. In einer Klasse habe ich eine andere Klasse namens " crimeScene " und wollen nach einer Eigenschaft von " sortieren crimeScene ".

Das funktioniert wie ein Zauber:

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

30voto

leviathan Punkte 10840

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

Für dieses spezielle Beispiel nehme ich an, dass die Objekte in Ihrem Array eine 'position' Methode haben, die eine 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" Feld wird automatisch wieder freigegeben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X