英文:
How do I properly loop through two nested json structures in golang
问题
我是你的中文翻译助手,以下是你要翻译的内容:
我刚开始学习Go语言。我有两个相同的嵌套的JSON结构,每个结构都填充了两个API调用的输出。一个调用获取CPU指标,另一个调用获取内存指标。我可以分别解组每个结构,并打印出项目名称以及CPU和内存的值,尽管这需要使用两个不同的代码块。我遇到的问题是,我希望能够在同一行上打印出CPU和内存指标,紧挨着它们的项目名称。
这是我用于打印按项目分类的CPU指标的代码。它创建了一个漂亮的CSV格式输出:
// CPU指标
// 循环遍历月份、项目、CPU请求和CPU使用数据
fmt.Println("月份, 项目, CPU请求(核小时), CPU使用(核小时)\n")
for _, value_cpu := range rh_values_cpu.Data {
for _, val_cpu := range value_cpu.Projects {
str := val_cpu.Project
s := strings.Contains(str, "openshift")
if s == true {
continue
}
fmt.Printf("%s, %s, ", value_cpu.Date, val_cpu.Project)
for _, v_cpu := range val_cpu.Values {
fmt.Printf("%.1f, %.1f\n", v_cpu.Request.Value, v_cpu.Usage.Value)
}
}
}
我对内存指标也有类似的代码,也能正常工作。
这是我用于循环遍历这两个JSON结构的代码。我怀疑我没有正确使用嵌套循环,或者需要以不同的方式解决这个问题。
// CPU和内存指标
// 循环遍历月份、项目、CPU请求、CPU使用、内存请求和内存使用数据
fmt.Println("月份, 项目, CPU请求(核小时), CPU使用(核小时), 内存请求(兆字节), 内存使用(兆字节)\n")
for _, value_cpu := range rh_values_cpu.Data {
for _, value_mem := range rh_values_MEM.Data {
for _, val_cpu := range value_cpu.Projects {
for _, val_mem := range value_mem.Projects {
str := val_cpu.Project
s := strings.Contains(str, "openshift")
if s == true {
continue
}
fmt.Printf("%s, %s, ", value_cpu.Date, val_cpu.Project)
for _, v_cpu := range val_cpu.Values {
fmt.Printf("%.1f, %.1f ", v_cpu.Request.Value, v_cpu.Usage.Value)
for _,v_mem := range val_mem.Values {
fmt.Printf("%.1f, %.1f\n", v_mem.Request.Value, v_mem.Usage.Value)
}
}
}
}
}
}
这是其中一个JSON结构的片段:
type RH_Output_MEM struct {
Meta struct {
Count int `json:"count"`
Others int `json:"others"`
Currency string `json:"currency"`
Filter struct {
Resolution string `json:"resolution"`
TimeScopeValue string `json:"time_scope_value"`
TimeScopeUnits string `json:"time_scope_units"`
Limit int `json:"limit"`
Offset int `json:"offset"`
} `json:"filter"`
GroupBy struct {
Project []string `json:"project"`
} `json:"group_by"`
OrderBy struct {
} `json:"order_by"`
Exclude struct {
} `json:"exclude"`
Total struct {
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Request struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"request"`
Limit struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"limit"`
Capacity struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"capacity"`
Infrastructure struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"infrastructure"`
Supplementary struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"supplementary"`
Cost struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"cost"`
} `json:"total"`
} `json:"meta"`
Links struct {
First string `json:"first"`
Next string `json:"next"`
Previous interface{} `json:"previous"`
Last string `json:"last"`
} `json:"links"`
Data []struct {
Date string `json:"date"`
Projects []struct {
Project string `json:"project"`
Values []struct {
Date string `json:"date"`
Project string `json:"project"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Request struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"request"`
Limit struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"limit"`
Capacity struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"capacity"`
Classification string `json:"classification"`
SourceUUID []string `json:"source_uuid"`
Clusters []string `json:"clusters"`
Infrastructure struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"infrastructure"`
Supplementary struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"supplementary"`
Cost struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"cost"`
} `json:"values"`
} `json:"projects"`
} `json:"data"`
}
这是我运行程序时得到的输出片段。你可以看到,日期、项目和内部循环(CPU指标)重复出现,而外部循环(内存指标)运行:
我希望每个项目有一行输出(月份、项目、CPU指标、内存指标)。
月份, 项目, CPU请求(核小时), CPU使用(核小时), 内存请求(兆字节), 内存使用(兆字节)
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 4353.2
2022-12, amq-demo-streams, 0.0, 34.0, 1115.6, 1081.4
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 10675.9
2022-12, amq-demo-streams, 0.0, 34.0, 100.9, 284.0
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 70064.5
2022-12, amq-demo-streams, 0.0, 34.0, 773088.9, 427757.8
2022-12, amq-demo-streams, 0.0, 34.0, 9440.0, 11610.3
2022-12, amq-demo-streams, 0.0, 34.0, 9471.3, 11696.9
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 2455.2
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 3.3
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 0.0
2022-12, amq-demo-streams, 0.0, 34.0, -0.3, 0.0
2022-12, amq-demo-streams, 0.0, 34.0, 3785.0, 6610.4
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 1007.8
2022-12, amq-demo-streams, 0.0, 34.0, 757.0, 883.0
2022-12, amq-demo-streams, 0.0, 34.0, 1009.4, 1613.4
2022-12, amq-demo-streams, 0.0, 34.0, 378.5, 413.5
2022-12, amq-demo-streams, 0.0, 34.0, 908.4, 2856.8
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 248.7
2022-12, amq-demo-streams, 0.0, 34.0, 66873.8, 21035.3
2022-12, amq-demo-streams, 0.0, 34.0, 353.3, 611.9
2022-12, amq-demo-streams, 0.0, 34.0, 10203.6, 12418.3
2022-12, amq-demo-streams, 0.0, 34.0, 504.7, 398.3
2022-12, amq-demo-streams, 0.0, 34.0, 1135.5, 2248.5
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 610.6
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 370.6
英文:
I am new to Go. I have 2 identical json nested structures that are each populated with the output of 2 api calls. One call fetches cpu and the other memory metrics. I can unmarshal each of them individually and print out the project name and values of cpu and memory, albeit in 2 separate code blocks. The problem I am having is that I would like to print out both cpu and memory metrics on the same line, next to their project name.
Here is the code I am using to print out the CPU metrics by Project. It creates a nice CSV formatted output:
// CPU Metrics
// Loop through the data for the Month, Project, CPU requests, and CPU Usage
fmt.Println("Month, Project, CPU Request(Core hours), CPU Usage(Core hours)\n")
for _, value_cpu := range rh_values_cpu.Data {
for _, val_cpu := range value_cpu.Projects {
str := val_cpu.Project
s := strings.Contains(str, "openshift")
if s == true {
continue
}
fmt.Printf("%s, %s, ", value_cpu.Date, val_cpu.Project)
for _, v_cpu := range val_cpu.Values {
fmt.Printf("%.1f, %.1f\n", v_cpu.Request.Value, v_cpu.Usage.Value)
}
}
}
I have similar code for the memory metrics which also works fine.
Here is the code I am using to loop through the two json structures. I suspect that I'm not using the nested loops properly or need to solve the problem differently.
// CPU & Memory Metrics
// Loop through the data for the Month, Project, CPU requests, CPU Usage, Memory requests, and Memory Usage
fmt.Println("Month, Project, CPU Request(Core hours), CPU Usage(Core hours) Memory Request(mBytes), Memory Usage(mBytes)\n")
for _, value_cpu := range rh_values_cpu.Data {
for _, value_mem := range rh_values_MEM.Data {
for _, val_cpu := range value_cpu.Projects {
for _, val_mem := range value_mem.Projects {
str := val_cpu.Project
s := strings.Contains(str, "openshift")
if s == true {
continue
}
fmt.Printf("%s, %s, ", value_cpu.Date, val_cpu.Project)
for _, v_cpu := range val_cpu.Values {
fmt.Printf("%.1f, %.1f ", v_cpu.Request.Value, v_cpu.Usage.Value)
for _,v_mem := range val_mem.Values {
fmt.Printf("%.1f, %.1f\n", v_mem.Request.Value, v_mem.Usage.Value)
}
}
}
}
}
}
And here is of one the json structures:
type RH_Output_MEM struct {
Meta struct {
Count int `json:"count"`
Others int `json:"others"`
Currency string `json:"currency"`
Filter struct {
Resolution string `json:"resolution"`
TimeScopeValue string `json:"time_scope_value"`
TimeScopeUnits string `json:"time_scope_units"`
Limit int `json:"limit"`
Offset int `json:"offset"`
} `json:"filter"`
GroupBy struct {
Project []string `json:"project"`
} `json:"group_by"`
OrderBy struct {
} `json:"order_by"`
Exclude struct {
} `json:"exclude"`
Total struct {
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Request struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"request"`
Limit struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"limit"`
Capacity struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"capacity"`
Infrastructure struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"infrastructure"`
Supplementary struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"supplementary"`
Cost struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"cost"`
} `json:"total"`
} `json:"meta"`
Links struct {
First string `json:"first"`
Next string `json:"next"`
Previous interface{} `json:"previous"`
Last string `json:"last"`
} `json:"links"`
Data []struct {
Date string `json:"date"`
Projects []struct {
Project string `json:"project"`
Values []struct {
Date string `json:"date"`
Project string `json:"project"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Request struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"request"`
Limit struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"limit"`
Capacity struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"capacity"`
Classification string `json:"classification"`
SourceUUID []string `json:"source_uuid"`
Clusters []string `json:"clusters"`
Infrastructure struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"infrastructure"`
Supplementary struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"supplementary"`
Cost struct {
Raw struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string `json:"units"`
} `json:"total"`
} `json:"cost"`
} `json:"values"`
} `json:"projects"`
} `json:"data"`
}
And here is a snippet of the output I am getting when running the program. As you can see, the Date, Project, and inner loop (CPU metrics) repeats itself, while the outer loop (Memory metrics) runs:
I'm looking for an output where I have one line per project (Month, Project, CPU metrics, Memory metrics)
Month, Project, CPU Request(Core hours), CPU Usage(Core hours) Memory Request(mBytes), Memory Usage(mBytes)
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 4353.2
2022-12, amq-demo-streams, 0.0, 34.0, 1115.6, 1081.4
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 10675.9
2022-12, amq-demo-streams, 0.0, 34.0, 100.9, 284.0
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 70064.5
2022-12, amq-demo-streams, 0.0, 34.0, 773088.9, 427757.8
2022-12, amq-demo-streams, 0.0, 34.0, 9440.0, 11610.3
2022-12, amq-demo-streams, 0.0, 34.0, 9471.3, 11696.9
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 2455.2
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 3.3
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 0.0
2022-12, amq-demo-streams, 0.0, 34.0, -0.3, 0.0
2022-12, amq-demo-streams, 0.0, 34.0, 3785.0, 6610.4
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 1007.8
2022-12, amq-demo-streams, 0.0, 34.0, 757.0, 883.0
2022-12, amq-demo-streams, 0.0, 34.0, 1009.4, 1613.4
2022-12, amq-demo-streams, 0.0, 34.0, 378.5, 413.5
2022-12, amq-demo-streams, 0.0, 34.0, 908.4, 2856.8
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 248.7
2022-12, amq-demo-streams, 0.0, 34.0, 66873.8, 21035.3
2022-12, amq-demo-streams, 0.0, 34.0, 353.3, 611.9
2022-12, amq-demo-streams, 0.0, 34.0, 10203.6, 12418.3
2022-12, amq-demo-streams, 0.0, 34.0, 504.7, 398.3
2022-12, amq-demo-streams, 0.0, 34.0, 1135.5, 2248.5
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 610.6
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 370.6
答案1
得分: 0
我允许自己使用更简单的结构定义。您可以根据自己的结构随时调整此代码。
type Cpu struct {
Project string
Data []Data
}
type Memory struct {
Project string
Data []Data
}
type Data struct {
Date string
Projects []Project
}
type Project struct {
Project string
Values []struct {
Request float64
Value float64
}
}
func CSVOutput(cpu Cpu, mem Memory) error {
// 如果cpu和memory的数据长度不相等,则返回错误
if len(cpu.Data) != len(mem.Data) {
return fmt.Errorf("cpu.Data和mem.Data的长度不相等")
}
// 打印CSV文件头部
fmt.Println("月份, 项目, CPU请求(核心小时), CPU使用(核心小时), 内存请求(MB), 内存使用(MB)")
for i := range cpu.Data {
cpuData := cpu.Data[i]
memData := mem.Data[i]
// 使用Errorf的格式添加错误上下文
if len(cpuData.Projects) != len(memData.Projects) {
return fmt.Errorf("cpu.Data[%d].Projects和mem.Data[%d].Projects的长度不相等", i, i)
}
for j := range cpuData.Projects {
cpuProject := cpuData.Projects[j]
memProject := memData.Projects[j]
if len(cpuProject.Values) != len(memProject.Values) {
return fmt.Errorf("cpu.Data[%d].Projects[%d].Values和mem.Data[%d].Projects[%d].Values的长度不相等", i, j, i, j)
}
name := cpuProject.Project
date := cpuData.Date
// 如果cpu项目涉及openshift,则跳过
if strings.Contains(name, "openshift") {
continue
}
for k := range cpuProject.Values {
cpuValue := cpuProject.Values[k]
memValue := memProject.Values[k]
fmt.Printf("%s, %s, %.1f, %.1f, %.1f, %.1f", date, name, cpuValue.Request, cpuValue.Value, memValue.Request, memValue.Value)
}
}
}
return nil
}
此代码仅在接收到与内存数据相同数量的CPU数据时才有效。
如果不是这种情况,您将需要找到一种将特定的CPU数据与其内存等效数据关联起来的方法。
如果您认为可能会出现这种情况,我们可以进一步讨论此问题。
英文:
I allowed myself to use simpler struct definition. You can always adapt this code to your structs.
type Cpu struct {
Project string
Data []Data
}
type Memory struct {
Project string
Data []Data
}
type Data struct {
Date string
Projects []Project
}
type Project struct {
Project string
Values []struct {
Request float64
Value float64
}
}
func CSVOutput(cpu Cpu, mem Memory) error {
// Returns an error if cpu & memory's data are the same length
if len(cpu.Data) != len(mem.Data) {
return fmt.Errorf("cpu.Data and mem.Data don't have the same length")
}
// Printing CSV file header
fmt.Println("Month, Project, CPU Request(Core hours), CPU Usage(Core hours) Memory Request(mBytes), Memory Usage(mBytes)")
for i := range cpu.Data {
cpuData := cpu.Data[i]
memData := mem.Data[i]
// Using the format from Errorf to add context to the error
if len(cpuData.Projects) != len(memData.Projects) {
return fmt.Errorf("cpu.Data[%d].Projects and mem.Data[%d].Projects don't have the same length", i, i)
}
for j := range cpuData.Projects {
cpuProject := cpuData.Projects[j]
memProject := memData.Projects[j]
if len(cpuProject.Values) != len(memProject.Values) {
return fmt.Errorf("cpu.Data[%d].Projects[%d].Values and mem.Data[%d].Projects[%d].Values don't have the same length", i, j, i, j)
}
name := cpuProject.Project
date := cpuData.Date
// Continue if the cpu project concerns openshift
if strings.Contains(name, "openshift") {
continue
}
for k := range cpuProject.Values {
cpuValue := cpuProject.Values[k]
memValue := memProject.Values[k]
fmt.Printf("%s, %s, %.1f, %.1f, %.1f, %.1f", date, name, cpuValue.Request, cpuValue.Value, memValue.Request, memValue.Value)
}
}
}
return nil
}
This code only works if you receive as much cpu's data as memory's data.
If it isn't the case, you will have to find a way to link a certain cpu's data to its memory equivalent.
This issue can be furthermore discussed if you think the situation might show up.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论