How do you sort dates in a dictionary?

I am having trouble sorting the next dictionary, so it prints in the old first-order list when printing.

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, ] 
+5
source share
4 answers

change / update: 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) } 
+7
source

In Swift 3 Date objects are now comparable, we can accomplish what you want:

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

The above code does a one-time mapping of key / value pairs with tuples, where the first element is a Date object and the second entry in the tuple is a singleton dictionary containing a key / value pair. Then it sorts the array of tuples, and then displays the sorted array to extract the key / value pairs, so you are left with an array of singleton dictionaries from the original data structure.

When sorting, you want to avoid expensive operations during sort comparison operations. Converting date strings to dates is pretty slow. Performing this conversion during each comparison in sorting is additionally inefficient because you end up comparing each element in your array with several other elements, so that you do the transcoded conversions over and over again.

+2
source

Dictionaries are not sorted, so you need to convert them to an array. The map function can do this for you. In addition, the rows cannot be sorted as intended, so you need to either rebuild the row in yyyy-MM-dd format or convert it to a date.

But as soon as you do this, you can sort the array. For example, using functional programming in Swift, you can do something like the following, which uses map to convert the dictionary into an array of tuples, and then uses sorted to sort them, using NSDateFormatter to convert strings to dates:

 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 } 

Although this has some simplicity, it is probably a bit inefficient, calling dateFromString more than we need. So, I probably would have a map function to add an NSDate object to an array of tuples, and then sorted can use an existing NSDate object:

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

This final map pulls out the NSDate object, but obviously you don't need to do this if you support NSDate in a tuple.

0
source

Your dates are strings, so they are sorted according to string sorting rules. Change the format to yyyy-MM-dd and they should be sorted correctly.

This assumes that you can rearrange the key value pairs in the dictionary first.

-1
source

All Articles