我的数据来源是
{“events”:[{“name”:“event 富 “ ”日期“: ”2018年7月21日“, ”时间“: ”7:00“, ”am_or_pm“: ”PM“, ”天“: ”星期六“, ”说明“:” 测试 “},{”name“:”event 酒吧”, “日期”: “2018年7月21日”, “时间”: “7:00”, “am_or_pm”: “PM”, “天”: “星期六”, “说明”: “TEST2”}, {“名”:“事件 foobar的”, “日期”: “2018年7月21日”, “时间”: “11:00”, “am_or_pm”: “PM”, “天”: “星期六”, “说明”: “TEST3”}] }
我尝试过字典/数组,但并没有真正接近我想要的结果。
将数据拉入数组:
var times = ["9:00","9:00","11:00"]
var names = ["event foo","event bar","event foobar"]
期望的输出:
["9:00", "11:00"]
[["event foo", "event bar"], ["event foobar"]]
任何指向在Swift中执行此操作的指标都表示赞赏。我的最终结果是希望按时间划分一个uitableview。
答案 0 :(得分:1)
我建议使用Decodable
解码JSON,并从组件创建完整日期。然后使用Dictionary(grouping:by:
)对数组进行分组。
首先创建一个DateFormatter
(如果您需要绝对的UTC日期,请取消注释时区行)
let dateFormatter : DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
// formatter.timeZone = TimeZone(secondsFromGMT: 0)!
formatter.dateFormat = "yyyy-MM-dd hh:mm a"
return formatter
}()
为根元素和events
数组创建两个结构。自定义初始值设定项会创建Date
实例
struct Root : Decodable {
let events : [Event]
}
struct Event : Decodable {
let date : Date
let name, description : String
private enum CodingKeys: String, CodingKey { case name, date, time, am_or_pm, description}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
description = try container.decode(String.self, forKey: .description)
let datePortion = try container.decode(String.self, forKey: .date)
let timePortion = try container.decode(String.self, forKey: .time)
let ampm = try container.decode(String.self, forKey: .am_or_pm)
let dateString = "\(datePortion) \(timePortion) \(ampm)"
guard let fullDate = dateFormatter.date(from: dateString) else {
throw DecodingError.dataCorruptedError(forKey: .date,
in: container,
debugDescription: "Date cannot be created")
}
date = fullDate
}
}
解码JSON并将数组分组
let jsonString = """
{"events": [{"name":"event foo","date":"2018-07-21","time":"7:00","am_or_pm":"PM","day":"Saturday","description":"test "}, {"name":"event bar","date":"2018-07-21","time":"7:00","am_or_pm":"PM","day":"Saturday","description":"test2"}, {"name":"event foobar","date":"2018-07-21","time":"11:00","am_or_pm":"PM","day":"Saturday","description":"test3"}]}
"""
do {
let data = Data(jsonString.utf8)
let decoder = JSONDecoder()
let result = try decoder.decode(Root.self, from: data)
let grouped = Dictionary(grouping: result.events, by: { $0.date})
print(grouped)
} catch {
print("error: ", error)
}
答案 1 :(得分:1)
如果使用Swift 4,您可以使用<ItemsControl>
<ItemsControl.ItemsPanel>
<!-- Grid with rows & columns ... -->
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Grid.Row="4" Grid.Column="2" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
和下标运算符的reduce(into:)
值:
default
这导致字典:
[“11:00”:[“event foobar”],“7:00”:[“event foo”,“event bar”]]
或者,正如Vadian建议的那样,您可以使用guard
let json = (try? JSONSerialization.jsonObject(with: data)) as? [String: [Any]],
let events = json["events"] as? [[String: String]] else {
return
}
let results = events.reduce(into: [String: [String]]()) { result, value in
guard let time = value["time"], let name = value["name"] else { return }
result[time, default: []].append(name)
}
,但如果您只需要Dictionary(grouping:,by:)
值,则必须map
,从而产生一系列元组:
name
[(“11:00”,[“foobar”事件]),(“7:00”,[“event foo”,“event bar”])]
就个人而言,就像Vadian建议的那样,我倾向于将let results = Dictionary(grouping: events, by: { $0["time"]! })
.map { ($0.key, $0.value.map { $0["name"]! })}
,date
和time
结合起来构建一个完整的am_or_pm
对象并使用上述其中一个图案。 E.g:
Date
或
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd h:mm a"
formatter.locale = Locale(identifier: "en_US_POSIX")
// if date/time values are in GMT, uncomment the following line:
//
// formatter.timeZone = TimeZone(secondsFromGMT: 0)
let results = events.reduce(into: [Date: [String]]()) { result, value in
guard
let timeString = value["time"],
let dateString = value["date"],
let amPm = value["am_or_pm"],
let date = formatter.date(from: dateString + " " + timeString + " " + amPm),
let name = value["name"] else { return }
result[date, default: []].append(name)
}
或者,如果Web服务在JSON中返回了日期,时间和上午/下午的单个ISO 8601 / RFC 3339字符串表示,则可以进一步简化。