我想根据日期对json数组中的数据进行排序, 以及与日期匹配的名义数据量。我使用swiftyjson和alamofire。
这是我的代码:
import UIKit
import Alamofire
import SwiftyJSON
class HomeViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
let createOrder = UserDefaults.standard.stringArray(forKey: "createOrder")
let nominal = UserDefaults.standard.stringArray(forKey: "nominal")
createOrder = createOrder?.sorted{ $0 < $1 }
print(createOrder?.description)
}
}
func fetchData(){
let url = ""
Alamofire.request(url, method: .get, encoding: URLEncoding.default).responseJSON{
(response) in
switch response.result {
case .success(let value):
let json = JSON(value)
print(json)
let jsonData = json["data"]["transaction"]
let data = jsonData.arrayValue.map{ $0["nominal"].string}
let createOrder = jsonData.arrayValue.map { $0["order_created"].string}
UserDefaults.standard.set(data, forKey: "nominal")
UserDefaults.standard.set(createOrder, forKey: "createOrder")
case .failure(let error):
print(error)
}
}
}
这是响应JSON
"data" : {
"transaction" : [
{
"order_created" : "2019-03-30 14:39:05",
"nominal" : "300000",
},
{
"order_created" : "2019-03-30 11:26:08",
"nominal" : "250000",
},
{
"order_created" : "2019-03-29 10:49:44",
"nominal" : "200000",
}
]
已取得的成就:
Optional("[\"2019-03-30 10:49:44\", \"2019-03-30 11:26:08\", \"2019-03-30 14:39:05\"]")
我在2019-03-30上获得的数据是2个名义上的300000和250000
在2019-03-29中,我得到1名义价值200000
我希望2019年3月30日的总名义金额为300000 + 250000 = 550000
所以结果我应该得到: 于2019-03-30总计500000 并且2019-03-29总计为200000
请帮助我
答案 0 :(得分:0)
首先为什么使用SwiftyJSON
并且内置Codable protocol
? Tutorial
第二:这个想法是像yyyy-MM-dd
那样按2019-03-30
对数据进行分组,这将需要更多工作。我为您的回复创建了可解码的版本,您可以检查
import Foundation
struct JsonData: Decodable {
let data: Transactions
}
struct Transactions: Decodable {
let transaction: [Transaction]
}
struct Transaction: Decodable {
let nominal: String
let orderCreated : Date
enum CodingKeys: String, CodingKey {
case orderCreated = "order_created"
case nominal
}
}
extension JsonData {
init(data: Data) throws {
self = try DatedDecoder().decode(JsonData.self, from: data)
}
}
fileprivate func DatedDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(DateFormatter.yyyyMMddHHmmss)
return decoder
}
extension DateFormatter {
// for modeling json data
static let yyyyMMddHHmmss : DateFormatter = {
let dateFormater = DateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormater.timeZone = TimeZone(abbreviation: "UTC")
dateFormater.locale = Locale(identifier: "en_US_POSIX")
return dateFormater
}()
// for grouping
static let yyyyMMdd: DateFormatter = {
let dateFormater = DateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd"
dateFormater.timeZone = TimeZone(abbreviation: "UTC")
dateFormater.locale = Locale(identifier: "en_US_POSIX")
return dateFormater
}()
}
您可以使用
// (data) is response of your API call
if let jsonData = try? JsonData(data: data){
let predicate: (Transaction) -> String = { transaction in
return DateFormatter.yyyyMMdd.string(from: transaction.orderCreated)
}
let groupingByDate : [String:[Transaction]] = Dictionary(grouping: jsonData.data.transaction, by: predicate)
let items = groupingByDate.map { item -> (date:String , value:Int) in
return (item.key , item.value.map({Int(String($0.nominal))!}).reduce(0, +))
}
// Final Items array is tuple with date and total nominal [(date: "2019-03-30", value: 550000), (date: "2019-03-29", value: 200000)
print(items)
}
上述解决方案的Json API响应
{
"data" : {
"transaction" : [
{
"order_created" : "2019-03-30 14:39:05",
"nominal" : "300000"
},
{
"order_created" : "2019-03-30 11:26:08",
"nominal" : "250000"
},
{
"order_created" : "2019-03-29 10:49:44",
"nominal" : "200000"
}
]
}
}
答案 1 :(得分:0)
您应该使用Codable
而不是SwiftyJSON
,因为它的输入更明确,但是直接回答关于SwiftyJSON
的问题,您可以这样做:
func processedTransactions(_ transactions: JSON) -> [(date: String, nominal: Double)] {
let processedTransactions = transactions
.arrayValue
.reduce(into: [String: Double]()) { (r, t) in
if let date = t["order_created"].stringValue.split(separator: " ").first {
let date = String(date)
r[date] = r[date, default: 0] + (Double(t["nominal"].stringValue) ?? 0)
}
}
.sorted { $0.key > $1.key }
.map { (date: $0.key, nominal: $0.value) }
return processedTransactions
}
func handleProcessedTransactions(_ transactions: [(date: String, nominal: Double)]) {
//do something with your sorted transactions
for t in transactions {
print(t.date, t.nominal)
}
}
这里,在processedTransactions(_:)
中,我们基本上遍历日期并仅基于YYYY-DD-MM
部分准备唯一的条目。
同时,我们记下与特定日期有关的名义价值的总和。
这是在reduce
部分完成的(我使用的逻辑是基本的字符串操作,但可以说它是错误的,所以可以随时重写该部分)
然后我们sort
,为了更好的可读性,我们map
将对象重新创建为元组(date: String, nominal: String)
然后,我们可以将其传递给handleProcessedTransactions(_:)
并对其进行所需的逻辑。
此外,您似乎正在使用UserDefaults
,因此代码的现有部分可能如下所示:
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
let json = UserDefaults.standard.object(forKey: "transactions")
let transactions = processedTransactions(JSON(json))
handleProcessedTransactions(transactions)
}
func fetchData() {
let url = ""
Alamofire
.request(url, method: .get, encoding: JSONEncoding.default)
.responseJSON { (response) in
switch response.result {
case .success(let value):
let json = JSON(value)
let transactionJSON = json["data"]["transaction"]
UserDefaults.standard.set(transactionJSON.arrayObject, forKey: "transactions")
//you probably want to handle it here too
let transactions = self.processedTransactions(transactionJSON)
self.handleProcessedTransactions(transactions)
case .failure(let error):
print(error)
}
}
}