如何在结构类型的结构中单元化变量
How do I unitize a variable in structure that is of type structure
我一直在阅读 JSON 文件。在帮助下,我已经能够这样做,但现在想扩展我从 JSON 文件中读取的内容。我想我已经正确设置了结构,但是当我从 ReadData class 创建结构的实例时,不明白如何初始化 Stock 结构中的元数据变量。我已经将 ? 放在 ReadData 中给我带来问题的代码行中
任何帮助,将不胜感激。
克里斯
下面是 JSON 数据和我的代码。
"Meta Data": {
"1. Information": "Daily Prices (open, high, low, close) and Volumes",
"2. Symbol": "VOO",
"3. Last Refreshed": "2021-09-22",
"4. Output Size": "Full size",
"5. Time Zone": "US/Eastern"
},
"Time Series (Daily)": {
"2021-09-22": {
"1. open": "402.1700",
"2. high": "405.8500",
"3. low": "401.2600",
"4. close": "403.9000",
"5. volume": "5979811"
},
struct Stock: Codable {
let metaData: MetaData
let timeSeriesDaily: [String : TimeSeriesDaily] // creates a dictionary, key = string : TimeSeriesDaily = value
enum CodingKeys: String, CodingKey {
case metaData = "Meta Data"
case timeSeriesDaily = "Time Series (Daily)"
}
}
struct MetaData: Codable {
let Information : String
let Symbol : String
let LastRefreshed : String
let OutputSize : String
let TimeZone: String
enum CodingKeys: String, CodingKey {
case Information = "1. Information"
case Symbol = "2. Symbol"
case LastRefreshed = "3. Last Refreshed"
case OutputSize = "4. Output Size"
case TimeZone = "5. Time Zone"
}
}
struct TimeSeriesDaily: Codable {
let Open, High, Low, Close: String
let Volume: String
enum CodingKeys: String, CodingKey {
case Open = "1. open"
case High = "2. high"
case Low = "3. low"
case Close = "4. close"
case Volume = "5. volume"
}
}
class ReadData: ObservableObject {
@Published var tmpData = Stock(metaData: ????? , timeSeriesDaily : [:])
init() {
loadData()
}
func loadData() {
guard let url = Bundle.main.url(forResource: "VOO", withExtension: "json")
else {
print("Json file not found")
return
}
let decoder = JSONDecoder()
do {
let data = try Data(contentsOf: url)
self.tmpData = try decoder.decode(Stock.self, from: data)
// print(self.tmpData)
} catch {
print(error)
}
}
}
struct ContentView: View {
@ObservedObject var vooData = ReadData()
var body: some View {
ScrollView {
VStack (alignment: .leading) {
let lastYear = getOneYearAgo()
let filteredDict = vooData.tmpData.timeSeriesDaily.filter { [=10=].key > lastYear } // Works
// let sortedFilteredDict = filteredDict.sorted { [=10=].key < .key } // Works
// let justCloseArray = sortedFilteredDict.map { ([=10=].key, [=10=].value.Close) } // returns array [(String, String)]
// let justCloseDict = Dictionary(uniqueKeysWithValues: justCloseArray) // returns dictionary with 1 key & 1 val
// let sortedCloseDict = justCloseDict.sorted { [=10=].key < .key } // works
let newDict = filteredDict.mapValues { Double([=10=].Close) }
let sortedNewDict = newDict.sorted { [=10=].key < .key }
Spacer()
// ForEach ( sortedCloseDict.map { ([=10=].key, [=10=].value) }, id: \.0 ) { keyValuePair in
ForEach ( sortedNewDict.map { ([=10=].key, [=10=].value) }, id: \.0 ) { keyValuePair in // map converts dictionary to arrap
HStack {
Text (keyValuePair.0)
Text ("\(keyValuePair.1!)")
}
}
Spacer()
} // end vstack
} .frame(width: 600, height: 400, alignment: .center) // end scroll view
}
}
您需要向其传递一个 MetaData
结构。 MetaData
的初始值设定项需要一些匹配其属性的 Strings
:
@Published var tmpData = Stock(metaData: MetaData(Information: "", Symbol: "", LastRefreshed: "", OutputSize: "", TimeZone: ""), timeSeriesDaily: [:])
一个提示是 Xcode 会自动为您完成其中的大部分内容。如果您开始输入 Stock
并让自动完成完成工作,您会看到它为 metaData
和 timeSeriesDaily
参数生成模板。
我一直在阅读 JSON 文件。在帮助下,我已经能够这样做,但现在想扩展我从 JSON 文件中读取的内容。我想我已经正确设置了结构,但是当我从 ReadData class 创建结构的实例时,不明白如何初始化 Stock 结构中的元数据变量。我已经将 ? 放在 ReadData 中给我带来问题的代码行中 任何帮助,将不胜感激。 克里斯 下面是 JSON 数据和我的代码。
"Meta Data": {
"1. Information": "Daily Prices (open, high, low, close) and Volumes",
"2. Symbol": "VOO",
"3. Last Refreshed": "2021-09-22",
"4. Output Size": "Full size",
"5. Time Zone": "US/Eastern"
},
"Time Series (Daily)": {
"2021-09-22": {
"1. open": "402.1700",
"2. high": "405.8500",
"3. low": "401.2600",
"4. close": "403.9000",
"5. volume": "5979811"
},
struct Stock: Codable {
let metaData: MetaData
let timeSeriesDaily: [String : TimeSeriesDaily] // creates a dictionary, key = string : TimeSeriesDaily = value
enum CodingKeys: String, CodingKey {
case metaData = "Meta Data"
case timeSeriesDaily = "Time Series (Daily)"
}
}
struct MetaData: Codable {
let Information : String
let Symbol : String
let LastRefreshed : String
let OutputSize : String
let TimeZone: String
enum CodingKeys: String, CodingKey {
case Information = "1. Information"
case Symbol = "2. Symbol"
case LastRefreshed = "3. Last Refreshed"
case OutputSize = "4. Output Size"
case TimeZone = "5. Time Zone"
}
}
struct TimeSeriesDaily: Codable {
let Open, High, Low, Close: String
let Volume: String
enum CodingKeys: String, CodingKey {
case Open = "1. open"
case High = "2. high"
case Low = "3. low"
case Close = "4. close"
case Volume = "5. volume"
}
}
class ReadData: ObservableObject {
@Published var tmpData = Stock(metaData: ????? , timeSeriesDaily : [:])
init() {
loadData()
}
func loadData() {
guard let url = Bundle.main.url(forResource: "VOO", withExtension: "json")
else {
print("Json file not found")
return
}
let decoder = JSONDecoder()
do {
let data = try Data(contentsOf: url)
self.tmpData = try decoder.decode(Stock.self, from: data)
// print(self.tmpData)
} catch {
print(error)
}
}
}
struct ContentView: View {
@ObservedObject var vooData = ReadData()
var body: some View {
ScrollView {
VStack (alignment: .leading) {
let lastYear = getOneYearAgo()
let filteredDict = vooData.tmpData.timeSeriesDaily.filter { [=10=].key > lastYear } // Works
// let sortedFilteredDict = filteredDict.sorted { [=10=].key < .key } // Works
// let justCloseArray = sortedFilteredDict.map { ([=10=].key, [=10=].value.Close) } // returns array [(String, String)]
// let justCloseDict = Dictionary(uniqueKeysWithValues: justCloseArray) // returns dictionary with 1 key & 1 val
// let sortedCloseDict = justCloseDict.sorted { [=10=].key < .key } // works
let newDict = filteredDict.mapValues { Double([=10=].Close) }
let sortedNewDict = newDict.sorted { [=10=].key < .key }
Spacer()
// ForEach ( sortedCloseDict.map { ([=10=].key, [=10=].value) }, id: \.0 ) { keyValuePair in
ForEach ( sortedNewDict.map { ([=10=].key, [=10=].value) }, id: \.0 ) { keyValuePair in // map converts dictionary to arrap
HStack {
Text (keyValuePair.0)
Text ("\(keyValuePair.1!)")
}
}
Spacer()
} // end vstack
} .frame(width: 600, height: 400, alignment: .center) // end scroll view
}
}
您需要向其传递一个 MetaData
结构。 MetaData
的初始值设定项需要一些匹配其属性的 Strings
:
@Published var tmpData = Stock(metaData: MetaData(Information: "", Symbol: "", LastRefreshed: "", OutputSize: "", TimeZone: ""), timeSeriesDaily: [:])
一个提示是 Xcode 会自动为您完成其中的大部分内容。如果您开始输入 Stock
并让自动完成完成工作,您会看到它为 metaData
和 timeSeriesDaily
参数生成模板。