【问题标题】:Convert JSON array of numbers into CGPoints in Objective-C or Swift在 Objective-C 或 Swift 中将 JSON 数字数组转换为 CGPoints
【发布时间】:2020-07-11 16:48:51
【问题描述】:

我正在尝试将 API 中的 JSON 转换为可在核心图形中使用的 cgpoint 数组。

JSON 看起来像:

{"date":"2017-01-05","open":119.34,"high":120.2,"low":119.1,"close":119.7,"adjusted_close":109.7062,"volume":4261070},{"date":"2017-01-06","open":118.93,"high":121.5,"low":118.52,"close":120.76,"adjusted_close":110.6777,"volume":4089186},{"date":"2017-01-09","open":120.76,"high":121.06,"low":120.33,"close":120.43,"adjusted_close":110.3754,"volume":3021844}

我对日期和关闭字段感兴趣,我想将它们转换成这种格式

 dataPoints:@[xy(val0,119.7),xy(val1,120.76),xy(val2,120.43)];

其中 val0...val3 是映射到图表 x 维度的日期,我已定义:

 #define xy(__x,__y) [NSValue valueWithCGPoint:CGPointMake(__x,__y)]

我不喜欢#define。这只是 CoreGraphics 现在使用的代码。如果有另一种方法可以做到这一点,那么结构或其他东西会很棒。

我知道如何使用以下方法将 JSON 解码为数组:

struct StockReport: Codable {
    let date: String
    let stockDatumOpen, high, low, close: Double
    let adjustedClose: Double
    let volume: Int

    enum CodingKeys: String, CodingKey {
        case date
        case stockDatumOpen = "open"
        case high, low, close
        case adjustedClose = "adjusted_close"
        case volume
    }
}

typealias StockData = [StockReport]

let stockData = try? newJSONDecoder().decode(StockData.self, from: jsonData)

不过,除此之外,我不确定如何创建 CGpoints 数组。

我想我可以将日期字符串转换为自 1970 年(纪元)以来的秒数,然后将它们缩放到坐标系。或者我可以使用数组的索引作为与每一天相对应的整数,但这就是我所得到的。 我应该遍历数组 stockData 并一一创建点吗?有没有更优雅的方式?

提前感谢您的任何建议。

【问题讨论】:

  • 您希望如何(以及为什么)将日期转换为 CGPoint 的 x?
  • 最终产品是一个图表,X 轴为日期,Y 轴为数值——常见于股票图表。因此 X 坐标需要映射到日期。所以需要有一些中间关系来将日期的坐标系映射到 cg 点值。已编辑问题以澄清
  • 我了解您在这里想要实现的目标,但我不明白您如何以及为什么要将日期放入 CGPoint。为 x 值设置一个计数器 (int),然后将日期放在一个单独的数组中并将它们用作 x 线上的标签不是更好吗?
  • 可能。我不习惯使用 CGPoints,并且对如何使用它们的数组感到困惑。事实上,数据点数组甚至不是 CGpoints 数组。这是别的东西..我猜是 NSValues 的 xy 或 dataPoints 数组
  • 所以你的集合中的每个日期都将被枚举为 1,2,3 并用作 x 值,而自参考日期以来的日期时间间隔将用于表示 y 值?

标签: json objective-c swift nsarray cgpoint


【解决方案1】:

假设您收到一个有效的 json 字符串(您发布的字符串不是有效的 json 字符串。您可以按日期对对象进行排序(如果它们尚未排序),枚举元素并将 CGPoint 初始化为关注:


let json = """
    [{"date":"2017-01-05",
     "open":119.34,
     "high":120.2,
     "low":119.1,
     "close":119.7,
     "adjusted_close":109.7062,
     "volume":4261070},
    {"date":"2017-01-06",
     "open":118.93,
     "high":121.5,
     "low":118.52,
     "close":120.76,
     "adjusted_close":110.6777,
     "volume":4089186},
    {"date":"2017-01-09",
     "open":120.76,
     "high":121.06,
     "low":120.33,
     "close":120.43,
     "adjusted_close":110.3754,
     "volume":3021844}]
"""

do {
    let stocks = try JSONDecoder().decode([StockReport].self, from: Data(json.utf8))
    let points = stocks.sorted{$0.date < $1.date}.enumerated().map {
        CGPoint(x: Double($0.offset), y: $0.element.close)
    }
    print(points)
} catch {
    print(error)
}

这将打印出来

[(0.0, 119.7), (1.0, 120.76), (2.0, 120.43)]

【讨论】:

  • 只是无缘无故地否决答案不会帮助 OP 和/或未来的读者。对我的答案有什么问题发表评论,以便我可以尝试改进和/或修复它,如果它有问题。
  • 这就像一个魅力。非常有效和优雅地回答了这个问题。
猜你喜欢
  • 2011-09-28
  • 2016-08-30
  • 1970-01-01
  • 2019-08-25
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多