2009-07-15 4 views
81

Ho un NSArray che contiene le stringhe di data (cioè NSString) in questo modo: "Gio 21 9 mag 19:10:09 -0700"Sort NSArray di stringhe di data o di oggetti

ho bisogno di ordinare la NSArray per data. Ho pensato prima di convertire la stringa della data in un oggetto NSDate, ma mi sono bloccato su come ordinare dall'oggetto NSDate.

Grazie.

+0

rimarcato dal momento che questo è legato al quadro Fondazione, e non specifiche per iPhone. –

risposta

108

Conservare le date come NSDate oggetti in un array NS (Mutevole), quindi utilizzare -[NSArray sortedArrayUsingSelector: o -[NSMutableArray sortUsingSelector:] e passano @selector(compare:) come parametro. Il metodo -[NSDate compare:] ordinerà le date in ordine crescente per te. È più semplice della creazione di un NSSortDescriptor e molto più semplice della scrittura della propria funzione di confronto. (NSDate oggetti sapere come si confrontano l'un l'altro, almeno nel modo più efficiente come abbiamo potuto sperare di ottenere con il codice personalizzato.)

+11

Non è chiaro se la domanda originale riguardasse l'ordinamento di una matrice di date o l'ordinamento di una matrice di oggetti con un campo data. Questo è l'approccio più semplice se è il primo, ma se è il secondo, NSSortDescriptor è la strada da percorrere. – smorgan

+0

@smorgan in che modo NSSortDescriptor gestisce le date nulle? – Ash

+0

Grazie per il vostro aiuto, penso che dovremmo leggere di più in Apple Docs ma sembra così noioso, finché non lo usate. – Abo3atef

4

Una volta che avete un NSDate, è possibile creare un NSSortDescriptor con initWithKey:ascending: e quindi utilizzare sortedArrayUsingDescriptors: per fare l'ordinamento.

+0

Questo approccio funzionerà, ma usando -sortedArrayUsingSelector: è un po 'più semplice e non richiede la creazione di un oggetto extra. –

+0

Pre-editing, la domanda menzionata "una 'data' key", quindi ho pensato che questa fosse davvero una matrice di oggetti/dizionari che aveva una data come un campo, non una serie di date non elaborate. In questo caso ordinatiArrayUsingSelector: è più complesso, poiché richiede la scrittura di una routine di ordinamento personalizzata per eseguire la ricerca. – smorgan

+0

Sì, scusa per qualsiasi confusione - ho ripulito quel riferimento dal momento che stava solo dicendo che stava conservando il suo array con un tasto 'data', e ho capito che rendeva la domanda più confusa. Hai sicuramente ragione riguardo la complessità relativa data una struttura dati più complessa. –

5

È possibile utilizzare sortedArrayUsingFunction:context:. Ecco un esempio:

NSComparisonResult dateSort(NSString *s1, NSString *s2, void *context) { 
    NSDate *d1 = [NSDate dateWithString:s1]; 
    NSDate *d2 = [NSDate dateWithString:s2]; 
    return [d1 compare:d2]; 
} 

NSArray *sorted = [unsorted sortedArrayUsingFunction:dateSort context:nil]; 

Quando si utilizza un NSMutableArray, è possibile utilizzare sortArrayUsingFunction:context: invece.

+8

Questa è una cattiva idea: una funzione di confronto dovrebbe essere veloce e non dovrebbe essere necessario creare oggetti NSDate dalle stringhe per ciascun confronto. Se si sta già utilizzando - [Confronto NSDate:], è sufficiente memorizzare le date nell'array e utilizzare -sortedArrayUsingSelector: direttamente. –

+0

Penso che questa sia una buona soluzione se si stanno ordinando oggetti che hanno già un campo NSDate. No? – GnarlyDog

+1

Se la matrice contiene già oggetti 'NSDate', è possibile usare la mia risposta sopra, o anche usare' - [NSMutableArray sortUsingComparator:] ', che è stato aggiunto in 10.6. –

111

Se ho un NSMutableArray di oggetti con un campo "BEGINDATE" di tipo NSDate Se si utilizza una NSSortDescriptor come di seguito:

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE]; 
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
[sortDescriptor release]; 
+3

So che è passato molto tempo (quando è stata accettata la risposta precedente non ci sarebbe stato ancora NSSortDescriptor), ma per uso futuro questa dovrebbe essere la risposta corretta. – Vive

+1

pensa anche tu;) – vinzenzweber

+1

Questa è una soluzione eccezionale. Ho risolto il mio problema in poche righe di codice.Thanx a tonnellata @vinzenzweber –

9

È possibile utilizzare i blocchi per ordinare al suo posto:

sortedDatesArray = [[unsortedDatesArray sortedArrayUsingComparator: ^(id a, id b) { 
    NSDate *d1 = [NSDate dateWithString: s1]; 
    NSDate *d2 = [NSDate dateWithString: s2]; 
    return [d1 compare: d2]; 
}]; 

ti suggerisco di convertire tutte le stringhe di date prima della cernita di non fare la conversione m Minuti di quanto non ci siano voci data. Qualsiasi algoritmo di ordinamento vi darà più stringa per conversioni di data rispetto al numero di elementi nella matrice (a volte sostanzialmente più)

un po 'più su blocchi di ordinamento: http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html

+0

Questa è una variante della stessa idea subottimale presentato da @notoop. In ogni caso, la conversione a NSDate prima è sicuramente la strada da percorrere. –

+1

qual è l'idea ottimale? –

+0

Ha praticamente appena messo la mia risposta con la risposta di @ notoop ..... abbastanza inutile doppio post quelli se mi chiedete .... – TheCodingArt

16

Si può anche usare qualcosa come il seguente:

//Sort the array of items by date 
    [self.items sortUsingComparator:^NSComparisonResult(id obj1, id obj2){ 
     return [obj2.date compare:obj1.date]; 
    }]; 

Ma questo si assume che la data è memorizzato come un NSDate piuttosto una NString, che dovrebbe essere un problema per fare/fare. Preferibilmente, raccomando anche di archiviare i dati nel suo formato raw. Rende più facile manipolare in situazioni come questa.

1

Modificare questa

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE]; 
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
[sortDescriptor release]; 

Per

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:TRUE]; 
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
[sortDescriptor release]; 

Basta modificare la chiave: deve essere Date sempre

4

Cosa ha funzionato nel mio caso è stato il seguente:

 NSArray *aUnsorted = [dataToDb allKeys]; 
    NSArray *arrKeys = [aUnsorted sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
     NSDateFormatter *df = [[NSDateFormatter alloc] init]; 
     [df setDateFormat:@"dd-MM-yyyy"]; 
     NSDate *d1 = [df dateFromString:(NSString*) obj1]; 
     NSDate *d2 = [df dateFromString:(NSString*) obj2]; 
     return [d1 compare: d2]; 
    }];

Ho avuto un dizionario, in cui tutte le chiavi in ​​cui le date in formato gg-MM-aaaa. E allKeys restituisce i tasti del dizionario non ordinati e volevo presentare i dati in ordine cronologico.

0

Swift 3,0

myMutableArray = myMutableArray.sorted(by: { $0.date.compare($1.date) == ComparisonResult.orderedAscending })