按 JSON 数组对表视图进行分组
Group tableview by JSON array
我正在使用 swiftyJson 获取一些数据,一切都很好,我得到了一个这样的数组 ("horario_emp"):
[
{
"dia" : 1,
"itinerario" : 0,
"id_horarios" : 13,
"jornada" : "05:00:00 - 12:30:00",
"id_empresa" : 1
},
{
"dia" : 1,
"itinerario" : 1,
"id_horarios" : 11,
"jornada" : "12:00:00 - 19:00:00",
"id_empresa" : 1
},
{
"dia" : 2,
"itinerario" : 0,
"id_horarios" : 14,
"jornada" : "05:00:00 - 12:30:00",
"id_empresa" : 1
},
{
"dia" : 2,
"itinerario" : 1,
"id_horarios" : 15,
"jornada" : "12:00:00 - 19:00:00",
"id_empresa" : 1
},
{
"dia" : 4,
"itinerario" : 0,
"id_horarios" : 10,
"jornada" : "05:00:00 - 12:30:00",
"id_empresa" : 1
},
{
"dia" : 4,
"itinerario" : 1,
"id_horarios" : 12,
"jornada" : "12:00:00 - 19:00:00",
"id_empresa" : 1
}
]
我想知道如何按 "dia" 对数组进行分组?因为我想像这样将数据显示到 tableviewcell 中:
直径 1
乔纳达 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
直径 2
乔纳达 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
直径 4
乔纳达 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
这是我的代码:
class Horarios: NSObject{
var dia: Int?
var jornada: [String]?
}
我的控制器:
let horarios = Horarios()
var obj_horarios: [Horarios] = []
let res = JSON(data)
let status = res["status"].boolValue
if(status){
let info_empresa = res["data"]["empresas"]
for(_, sub_res):(String, JSON) in info_empresa{
let horario_emp = sub_res["horario"]
let allKeys = Set<String>(horario_emp.filter({!([=13=]["dia"].string?.isEmpty)!}).map{[=13=]["dia"].stringValue})
for key in allKeys {
var horarios = Horarios()
obj_horarios = horario_emp.filter({
[=13=]["dia"].string ?? "" == key
}).map({ (json) -> Horarios in
horarios.dia = json["dia"].intValue
horarios.jornada.append(json["jornada"].stringValue)
return horarios
})
}
}
self.tableView.reloadData()
}
我收到此错误 Value of tuple type 'JSON.Element' (aka '(String, JSON)') has no member 'subscript' in the line let allKeys....
我该如何分组?
这个答案不包括使用 SwiftyJSON,而是使用 Swift 4 中的原生 JSON 解析和 Codable
协议.我确信使用 SwiftyJSON 很棒,但是 JSON 的新本地处理使这个任务相当简单:
// jsonText is a String that contains the JSON text
let jsonText = "" // fill in the appropriate text
import Foundation
// the struct to decode into (called Foo for lack of a better name)
struct Foo : Codable {
let dia: Int
let itinerario: Int
let id_horarios: Int
let jornada: String
let id_empresa: Int
}
struct Horarios {
let dia: Int
let jornada: [String]
}
// push it into a Data and decode it
if let data = jsonText.data(using: .utf8),
let decoded = try? JSONDecoder().decode([Foo].self, from: data) {
let obj_horarios =
// group the Foo objects by the `dia` property as keys,
Dictionary(grouping: decoded, by: { [=10=].dia })
// convert the Foo objects into an array of `Horarios` structs
.map { Horarios(dia: [=10=].0, jornada: [=10=].1.map { [=10=].jornada }) }
// sort them by `dia`
.sorted { [=10=].dia < .dia }
print(obj_horarios)
// result:
// [Horarios(dia: 1, jornada: ["05:00:00 - 12:30:00", "12:00:00 - 19:00:00"]),
// Horarios(dia: 2, jornada: ["05:00:00 - 12:30:00", "12:00:00 - 19:00:00"]),
// Horarios(dia: 4, jornada: ["05:00:00 - 12:30:00", "12:00:00 - 19:00:00"])]
}
此外,如果您只关心键 dia
和 jornada
,那么您可以简化 Foo
struct
以仅包含这些属性:
struct Foo : Codable {
let dia: Int
let jornada: String
}
JSON 中的任何附加密钥在解码过程中都将被忽略。
Define class
class Horaios {
var dia:Int?
var itinerario:Int?
var id_horarios:Int?
var jornada:String?
var id_empresa:Int?
}
implement Sequence extension
public extension Sequence {
func categorise<U : Hashable>(_ key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
var dict: [U:[Iterator.Element]] = [:]
for el in self {
let key = key(el)
if case nil = dict[key]?.append(el) { dict[key] = [el] }
}
return dict
}
}
Call Below method and Output will be like this
dia 1 jordano 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
dia 2 jordano 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
dia 4 jordano 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
func parseJSON(jsonString:String) {
let jsonData = jsonString.data(using: String.Encoding.utf8)
//let groupedItems:[Int:[Horaios]?]?
do {
if let data = jsonData {
let parsedJSON = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableLeaves)
if let arr = parsedJSON as? [Any] {
var items = [Horaios]()
for item in arr {
if let dict = item as? [String:Any?] {
let obj = Horaios()
obj.dia = dict["dia"] as? Int
obj.itinerario = dict["itinerario"] as? Int
obj.id_horarios = dict["id_horarios"] as? Int
obj.jornada = dict["jornada"] as? String
obj.id_empresa = dict["id_empresa"] as? Int
items.append(obj)
}
}
items.sort(by: { (obj1, obj2) -> Bool in
if let x = obj1.dia, let y = obj2.dia {
return x < y
}
return false
})
let groups = items.categorise {[=10=].dia!}
let sorted = groups.sorted(by: { (x, y) -> Bool in
return x.key < y.key
})
for xx in sorted {
if let componets = groups[xx.key] {
var strings = [String]()
for x in componets {
if let ss = x.jornada {
strings.append(ss)
}
}
print("dia \(xx.key) jordano \(strings.joined(separator:" - "))")
}
}
}
}
}
catch {
}
}
我正在使用 swiftyJson 获取一些数据,一切都很好,我得到了一个这样的数组 ("horario_emp"):
[
{
"dia" : 1,
"itinerario" : 0,
"id_horarios" : 13,
"jornada" : "05:00:00 - 12:30:00",
"id_empresa" : 1
},
{
"dia" : 1,
"itinerario" : 1,
"id_horarios" : 11,
"jornada" : "12:00:00 - 19:00:00",
"id_empresa" : 1
},
{
"dia" : 2,
"itinerario" : 0,
"id_horarios" : 14,
"jornada" : "05:00:00 - 12:30:00",
"id_empresa" : 1
},
{
"dia" : 2,
"itinerario" : 1,
"id_horarios" : 15,
"jornada" : "12:00:00 - 19:00:00",
"id_empresa" : 1
},
{
"dia" : 4,
"itinerario" : 0,
"id_horarios" : 10,
"jornada" : "05:00:00 - 12:30:00",
"id_empresa" : 1
},
{
"dia" : 4,
"itinerario" : 1,
"id_horarios" : 12,
"jornada" : "12:00:00 - 19:00:00",
"id_empresa" : 1
}
]
我想知道如何按 "dia" 对数组进行分组?因为我想像这样将数据显示到 tableviewcell 中:
直径 1 乔纳达 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
直径 2 乔纳达 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
直径 4 乔纳达 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
这是我的代码:
class Horarios: NSObject{
var dia: Int?
var jornada: [String]?
}
我的控制器:
let horarios = Horarios()
var obj_horarios: [Horarios] = []
let res = JSON(data)
let status = res["status"].boolValue
if(status){
let info_empresa = res["data"]["empresas"]
for(_, sub_res):(String, JSON) in info_empresa{
let horario_emp = sub_res["horario"]
let allKeys = Set<String>(horario_emp.filter({!([=13=]["dia"].string?.isEmpty)!}).map{[=13=]["dia"].stringValue})
for key in allKeys {
var horarios = Horarios()
obj_horarios = horario_emp.filter({
[=13=]["dia"].string ?? "" == key
}).map({ (json) -> Horarios in
horarios.dia = json["dia"].intValue
horarios.jornada.append(json["jornada"].stringValue)
return horarios
})
}
}
self.tableView.reloadData()
}
我收到此错误 Value of tuple type 'JSON.Element' (aka '(String, JSON)') has no member 'subscript' in the line let allKeys.... 我该如何分组?
这个答案不包括使用 SwiftyJSON,而是使用 Swift 4 中的原生 JSON 解析和 Codable
协议.我确信使用 SwiftyJSON 很棒,但是 JSON 的新本地处理使这个任务相当简单:
// jsonText is a String that contains the JSON text
let jsonText = "" // fill in the appropriate text
import Foundation
// the struct to decode into (called Foo for lack of a better name)
struct Foo : Codable {
let dia: Int
let itinerario: Int
let id_horarios: Int
let jornada: String
let id_empresa: Int
}
struct Horarios {
let dia: Int
let jornada: [String]
}
// push it into a Data and decode it
if let data = jsonText.data(using: .utf8),
let decoded = try? JSONDecoder().decode([Foo].self, from: data) {
let obj_horarios =
// group the Foo objects by the `dia` property as keys,
Dictionary(grouping: decoded, by: { [=10=].dia })
// convert the Foo objects into an array of `Horarios` structs
.map { Horarios(dia: [=10=].0, jornada: [=10=].1.map { [=10=].jornada }) }
// sort them by `dia`
.sorted { [=10=].dia < .dia }
print(obj_horarios)
// result:
// [Horarios(dia: 1, jornada: ["05:00:00 - 12:30:00", "12:00:00 - 19:00:00"]),
// Horarios(dia: 2, jornada: ["05:00:00 - 12:30:00", "12:00:00 - 19:00:00"]),
// Horarios(dia: 4, jornada: ["05:00:00 - 12:30:00", "12:00:00 - 19:00:00"])]
}
此外,如果您只关心键 dia
和 jornada
,那么您可以简化 Foo
struct
以仅包含这些属性:
struct Foo : Codable {
let dia: Int
let jornada: String
}
JSON 中的任何附加密钥在解码过程中都将被忽略。
Define class
class Horaios {
var dia:Int?
var itinerario:Int?
var id_horarios:Int?
var jornada:String?
var id_empresa:Int?
}
implement Sequence extension
public extension Sequence {
func categorise<U : Hashable>(_ key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
var dict: [U:[Iterator.Element]] = [:]
for el in self {
let key = key(el)
if case nil = dict[key]?.append(el) { dict[key] = [el] }
}
return dict
}
}
Call Below method and Output will be like this
dia 1 jordano 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
dia 2 jordano 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
dia 4 jordano 05:00:00 - 12:30:00 - 12:00:00 - 19:00:00
func parseJSON(jsonString:String) {
let jsonData = jsonString.data(using: String.Encoding.utf8)
//let groupedItems:[Int:[Horaios]?]?
do {
if let data = jsonData {
let parsedJSON = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableLeaves)
if let arr = parsedJSON as? [Any] {
var items = [Horaios]()
for item in arr {
if let dict = item as? [String:Any?] {
let obj = Horaios()
obj.dia = dict["dia"] as? Int
obj.itinerario = dict["itinerario"] as? Int
obj.id_horarios = dict["id_horarios"] as? Int
obj.jornada = dict["jornada"] as? String
obj.id_empresa = dict["id_empresa"] as? Int
items.append(obj)
}
}
items.sort(by: { (obj1, obj2) -> Bool in
if let x = obj1.dia, let y = obj2.dia {
return x < y
}
return false
})
let groups = items.categorise {[=10=].dia!}
let sorted = groups.sorted(by: { (x, y) -> Bool in
return x.key < y.key
})
for xx in sorted {
if let componets = groups[xx.key] {
var strings = [String]()
for x in componets {
if let ss = x.jornada {
strings.append(ss)
}
}
print("dia \(xx.key) jordano \(strings.joined(separator:" - "))")
}
}
}
}
}
catch {
}
}