2015-04-10 15 views
5

Ho difficoltà a cercare di ordinare il seguente dizionario, in modo che venga stampato con il primo ordine di data più vecchio quando stampato.Come si ordinano le date in un dizionario?

var dayTotalDicTest: [String:Int] = 

      [ 
       "04-09-2015" : 4, 
       "04-10-2015" : 6, 
       "04-07-2015" : 8, 
       "03-28-2015" : 10, 
       "12-10-2014" : 12, 
       "12-10-2015" : 12, 

      ] 
+3

Nella maggior parte delle lingue, non è possibile ordinare le chiavi in ​​un dizionario. Non è questo il punto di un dizionario. Un dizionario è per l'inserimento e il recupero a tempo costante. E per le chiavi che non sono numeri interi. Se inserisci le coppie di valori chiave in un elenco, puoi ordinarlo. –

+0

dayTotalArrayTest non è un array è un dizionario. Non si può effettivamente ordinare un dizionario –

risposta

7

modifica/aggiornamento: Xcode 8.2.1 • Swift 3.0.2

extension String { 
    static let shortDateUS: DateFormatter = { 
     let formatter = DateFormatter() 
     formatter.calendar = Calendar(identifier: .iso8601) 
     formatter.locale = Locale(identifier: "en_US_POSIX") 
     formatter.dateStyle = .short 
     return formatter 
    }() 
    var shortDateUS: Date? { 
     return String.shortDateUS.date(from: self) 
    } 
} 

let dayTotalDicTest: [String:Int] = [ 
    "04-09-2015" : 4, 
    "04-10-2015" : 6, 
    "04-07-2015" : 8, 
    "03-28-2015" : 10, 
    "12-10-2014" : 12, 
    "12-10-2015" : 12] 

let myArrayOfTuples = dayTotalDicTest.sorted{ 
    guard let d1 = $0.key.shortDateUS, let d2 = $1.key.shortDateUS else { return false } 
    return d1 < d2 
} 

print(myArrayOfTuples) // [("12-10-2014", 12), ("03-28-2015", 10), ("04-07-2015", 8), ("04-09-2015", 4), ("04-10-2015", 6), ("12-10-2015", 12)]\n" 

for tuple in myArrayOfTuples { 
    print(tuple) 
} 
+0

Esattamente quello che mi serviva, grazie!Risolto anche i miei problemi di formulazione nella domanda, grazie ancora. – JideO

+0

Siete i benvenuti –

+0

@LeoDabus Il problema qui è che questo approccio di estensione è orribilmente inefficiente. Sicuramente non istanziare nuovi formattatori di date all'interno del metodo di estensione. Francamente, non dovresti nemmeno chiamare "dateFromString" all'interno della chiusura "ordinata". Se si dispone di un array di grandi dimensioni (ad esempio 1000 stringhe), questo algoritmo è circa 200 volte più lento rispetto ad altri approcci. La tua soluzione va bene per array banalmente piccoli, ma con array più grandi, questo è molto inefficiente. – Rob

-1

Le date sono stringhe, in modo che siano in fase di ordinamento in base alle regole di ordinamento string. Modificare il formato in yyyy-MM-dd e dovrebbero essere ordinati correttamente.

Si presume, badate bene, che è possibile riorganizzare coppie di valori chiave in un dizionario in primo luogo.

0

I dizionari non possono essere ordinati, quindi è necessario convertirlo in un array. La funzione map può farlo per te. Inoltre, le stringhe non possono essere ordinate come fornite, quindi è necessario ristrutturare la stringa nel formato yyyy-MM-dd o convertirla in data.

Ma una volta fatto, è possibile ordinare l'array. Ad esempio, utilizzando la programmazione funzionale a Swift, si potrebbe fare qualcosa di simile a quanto segue, che utilizza map per convertire il dizionario per una serie di tuple, e quindi utilizza sorted per ordinare questi, utilizzando NSDateFormatter per convertire le stringhe di date:

var dayTotalDictionary: [String:Int] = [ 
    "04-09-2015" : 4, 
    "04-10-2015" : 6, 
    "04-07-2015" : 8, 
    "03-28-2015" : 10, 
    "12-10-2014" : 12, 
    "12-10-2015" : 12 
] 

let formatter = NSDateFormatter() 
formatter.dateFormat = "MM-dd-yyyy" 

let dayTotalArray = map(dayTotalDictionary) { ($0, $1) } 
    .sorted() { formatter.dateFromString($0.0)!.compare(formatter.dateFromString($1.0)!) == .OrderedAscending } 

Mentre ciò gode di una certa semplicità, è probabilmente un po 'inefficiente, chiamando dateFromString più del necessario. Quindi, probabilmente hanno la funzione map aggiungere l'oggetto NSDate alla matrice di tuple, e quindi sorted possono usufruire dell'oggetto NSDate che è già presente:

let dayTotalArray = map(dayTotalDictionary) { (formatter.dateFromString($0)!, $0, $1) } // in Swift 2.0, use `dayTotalDictionary.map()` 
    .sorted() { ($0.0 as NSDate).compare($1.0 as NSDate) == .OrderedAscending }   // in Swift 2.0, use `sort` 
    .map() { (_, dateString, dayTotal) in (dateString, dayTotal) } 

Quella finale map tira fuori l'oggetto NSDate, ma chiaramente non hai bisogno di farlo se stai bene mantenendo lo NSDate nella tupla.

2

In Swift 3 oggetti Data sono ora paragonabili, siamo in grado di realizzare ciò che si vuole come segue:

let dayTotalDicTest: [String:Int] = [ 
    "04-09-2015" : 4, 
    "04-10-2015" : 6, 
    "04-07-2015" : 8, 
    "03-28-2015" : 10, 
    "12-10-2014" : 12, 
    "12-10-2015" : 12] 

//Create a date formatter to convert our date strings to Date objects 
let df = DateFormatter() 
df.dateFormat = "MM-dd-yyyy" 

let sortedArrayOfDicts = dayTotalDicTest 
    //First map to an array tuples: [(Date, [String:Int]] 
    .map{(df.date(from: $0.key)!, [$0.key:$0.value])} 

    //Now sort by the dates, using `<` since dates are Comparable. 
    .sorted{$0.0 < $1.0} 

    //And re-map to discard the Date objects 
    .map{$1} 

for item in sortedArrayOfDicts { 
    print(item) 
} 

Il codice sopra riportato esegue una mappatura una tantum delle coppie chiave/valore alle tuple in cui il primo elemento è un oggetto Date e la seconda voce nella tupla è un dizionario a elemento singolo contenente la coppia chiave/valore oriente. Quindi ordina l'array di tuple e quindi esegue il mapping della matrice ordinata per estrarre le coppie chiave/valore, quindi ciò che rimane è una serie di dizionari a elemento singolo dalla struttura dati originale.

Quando si ordina, si desidera evitare operazioni costose durante le operazioni di confronto dell'ordinamento. La conversione delle stringhe di date in date è abbastanza lenta. Effettuare tale conversione durante ogni confronto nell'ordinamento è inefficiente in più, perché si termina il confronto di ogni elemento dell'array con più altri elementi, quindi le conversioni string-to-date vengono eseguite più e più volte.

Problemi correlati