2012-03-12 20 views
28

Ho creato un descrittore di ordinamento per ordinare una risposta plist proveniente dal mio server. Funziona bene con la chiave di ordinamento con valori fino a 9. Con più di 10 voci vedo risultati bruschi con la chiave di ordinamento sistemata nell'ordine = 1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9Ordinamento dei valori NSString come se NSInteger utilizzasse NSSortDescriptor

NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sort" ascending:YES]; 
self.myList = [NSMutableArray arrayWithArray:[unsortedList sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]]; 

Come organizzarlo nell'ordine corretto di 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11?

risposta

44

È possibile farlo mediante l'attuazione di un blocco comparatore personalizzato durante la creazione NSSortDescriptor: documentazione

NSSortDescriptor *aSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sort" ascending:YES comparator:^(id obj1, id obj2) { 

    if ([obj1 integerValue] > [obj2 integerValue]) { 
     return (NSComparisonResult)NSOrderedDescending; 
    } 
    if ([obj1 integerValue] < [obj2 integerValue]) { 
     return (NSComparisonResult)NSOrderedAscending; 
    } 
    return (NSComparisonResult)NSOrderedSame; 
}]; 
self.myList = [NSMutableArray arrayWithArray:[unsortedList sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]]; 

Sede di Apple here

+1

si prega di notare che questa soluzione non funziona con CoreData fetchRequests, perché non accetta i descrittori basati su blocchi. – OlDor

7
NSMutableArray *list = [NSMutableArray arrayWithObjects:@"11",@"2",@"3",@"1", nil]; 
[list sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
    NSInteger firstInteger = [obj1 integerValue]; 
    NSInteger secondInteger = [obj2 integerValue]; 
    if(firstInteger > secondInteger) return NSOrderedDescending; 
    if(firstInteger == secondInteger) return NSOrderedSame; 
    return NSOrderedAscending; // edited 
}]; 

Nessuna garanzia sulle prestazioni

+0

Si noti che questa soluzione non funzionerà con CoreData fetchRequests, perché non accetta i descrittori in base ai blocchi. – OlDor

11

è necessario il vostro stringhe essere confrontato con l'opzione NSNumericSearch:

NSNumericSearch
Numeri all'interno stringhe vengono confrontate utilizzando valore numerico, cioè Name2.txt < Name7.txt < Name25.txt.

che richiede il metodo compare:options: da chiamare per il confronto.

Per fare questo, il descrittore tipo può utilizzare un NSComparator Block:

[NSSortDescriptor sortDescriptorWithKey:@"self" 
           ascending:YES 
          comparator:^(NSString * string1, NSString * string2){ 
              return [string1 compare:string2 
                  options:NSNumericSearch]; 
}]; 

o, addirittura, si può saltare il descrittore di sorta e semplicemente sort the array directly, utilizzando lo stesso blocco:

[unsortedList sortedArrayUsingComparator:^NSComparisonResult (NSString * string1, NSString * string2){ 
    return [string1 compare:string2 
        options:NSNumericSearch]; 
}]; 
+0

Piccola aggiunta: perché trasmettere a 'NSString'? Potresti passare 'NSString' direttamente invece di' id', renderlo più facile da leggere. :-) –

+0

Questo è un grande punto, @Blauesocke; Grazie! –

+0

nota che questa soluzione non funzionerà con CoreData fetchRequests, perché non accetta i descrittori in base ai blocchi. – OlDor

38

[list sortUsingSelector:@selector(localizedStandardCompare:)]; ordinerà l'elenco in un modo "umano" (quindi "11" verrà per ultimo, non tra "1" e "2"). Ma se vuoi davvero trattare queste stringhe come numeri, devi prima renderli numeri!

+1

molto più pulito in questo modo. – pir800

+0

perfetto! altre soluzioni non hanno funzionato per me, perché CoreData non accetta ordinamentoDiscript basato su blocchi. ma questo ha funzionato. – OlDor

+0

La migliore soluzione per me;) –

16
NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sort.intValue" ascending:YES]; 
self.myList = [NSMutableArray arrayWithArray:[unsortedList sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]]; 

Ordinamento basato sul valore del numero intero.

+0

Perfetto con la sua semplicità! – DonnaLea

+0

non ha funzionato. ottengo '0 1 10 11 12 ... 2 3 4' invece di '0 1 2 3 4 ... 10 11 12' – OlDor

+0

Risposta più semplice. Lavorato per valori interi molto bene –

0

Tutti i metodi di cui sopra richiedono una buona conoscenza delle basi da implementare; ma per i neofiti suggerisco il modo più semplice - per utilizzare il metodo di blocco nativo

NSArray* sortedArr =[fetchResults sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { 

    int aValue = [[a valueForKey:@"subgroupId"] intValue]; 
    int bValue = [[b valueForKey:@"subgroupId"] intValue]; 

    return aValue > bValue; 
}]; 
0

ingresso

{ 
    "seats": [{ 
     "seatNumber": "1" 
    }, { 
     "seatNumber": "10" 
    }, { 
     "seatNumber": "2" 
    }] 
} 

sorta usando [NSSortDescriptor sortDescriptorWithKey: @ ascendente "seatNumber": SI selettore: @selector (localizedStandardCompare :)]]. La chiave è usare localizedStandardCompare. Questo ti risolverà il problema.

NSArray *seats = [self.seats sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"seatNumber" ascending:YES selector:@selector(localizedStandardCompare:)]]]; 

uscita

{ 
    "seats": [{ 
     "seatNumber": "1" 
    }, { 
     "seatNumber": "2" 
    }, { 
     "seatNumber": "10" 
    }] 
} 

documentazione: https://developer.apple.com/documentation/foundation/nsstring/1409742-localizedstandardcompare

+0

Non si dovrebbe solo rispondere con il codice, ma provare a dare una descrizione/spiegazione di ciò che fa, come risolve il problema, ecc ... –

Problemi correlati