Reputation: 141
Hello I have a dictionary contained in an array. Something like this:
var array = [[String: Any]] ()
After executing a certain code, the array is filled with the following example data:
array = [["Date": "Sat-16-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30" ]]
["Date": "Thu-14-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30"]]
["Date": "Fri-15-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30"]]
["Date": "Mon-11-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30"]]
["Date": "Sun-10-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30"]]
["Date": "Wed-13-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30"]]
["Date": "Sat-09-May", "sched": ["8:00 - 8:30", "8:30 - 9:00", "09:00 - 09:30"]]
]
What I need is to be able to sort them by day of the week. Because he always prints it to me in a different order
I have found solutions to sort dictionaries, but not to sort dictionaries contained in an array. How can I access the dictionary key (Date) to order them according to that data?
Thank you :)
Upvotes: 0
Views: 68
Reputation: 151
First of all, the example data has a few inconsistencies in the date formatting, as mentioned by @Larme. This answer assumes that the example data was intended as below, and adds "AM":
array = [
["Date": "Sat-16-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Thu-14-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Fri-15-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Mon-11-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Sun-10-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Wed-13-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Sat-09-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]]
]
Your example data indicates that you are storing durations for dates. The best way to sort these is by using [Date: [DateInterval]]
. When you want to display these dates and durations as strings, you can use a DateFormatter
for the Date
's and a DateIntervalFormatter
for the DateInterval
's. This data can be stored as a Dictionary
and sorted into an Array
of tuples with the keys and values, [(key: Date, value: [DateInterval])]
.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "eee-dd-MMM"
let intervalFormatter = DateIntervalFormatter()
intervalFormatter.dateStyle = .none
intervalFormatter.timeStyle = .short
var newDict = [Date: [DateInterval]]()
The sorted Array:
let arrayOfTuples = newDict.sorted { (left, right) -> Bool in
left.key > right.key
}
Any time you need to display one of these dates or intervals, you can simply use:
dateFormatter.string(from: aDate) // replace aDate
intervalFormatter.string(from: aDateInterval) // replace aDateInterval
If you want to use your example data as a literal for testing or otherwise, you can convert it to [Date: [DateInterval]]
using this code:
let disposableFormatter = DateFormatter()
disposableFormatter.dateFormat = "eee-dd-MMMhh:mm a"
array.forEach { dictionaryPiece in
let dateString = dictionaryPiece["Date"] as! String
let date = dateFormatter.date(from: dateString)!
let sched = dictionaryPiece["sched"] as! [String]
newDict[date] =
sched.map { (stringInterval: String) -> DateInterval in
let start = disposableFormatter.date(from: dateString + stringInterval.components(separatedBy: " - ")[0])!
let end = disposableFormatter.date(from: dateString + stringInterval.components(separatedBy: " - ")[1])!
return DateInterval(start: start, end: end)
}
}
Finally, if you simply want to sort your data exactly as it is, you can just use Array.sort(by areInIncreasingOrder: (Element, Element) throws -> Bool)
, as implemented below.
var array = [[String: Any]] ()
array = [
["Date": "Sat-16-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Thu-14-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Fri-15-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Mon-11-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Sun-10-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Wed-13-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]],
["Date": "Sat-09-May", "sched": ["08:00 AM - 08:30 AM", "08:30 AM - 09:00 AM", "09:00 AM - 09:30 AM"]]
]
let formatter = DateFormatter()
formatter.dateFormat = "eee-dd-MMM"
array.sort { (left, right) -> Bool in
formatter.date(from: left["Date"] as! String)! > formatter.date(from: right["Date"] as! String)!
}
Upvotes: 1
Reputation: 17844
Taking your data structure as-is, you can sort your array(!) like this
var arr = [[String: Any]] ()
arr.sort { (dict1, dict2) -> Bool in
let date1 = dict1["Date"] as? String ?? ""
let date2 = dict2["Date"] as? String ?? ""
return date1 < date2
}
That said, if at all possible, you should avoid stringly typed APIs that rely on [String: Any]
dictionaries and the resulting casting and optional checking hassle.
Upvotes: 0