如何在go中使用模板进行排名
我有一些json格式的数据如何在go中使用模板进行排名,go,go-templates,Go,Go Templates,我有一些json格式的数据 [ { "group":"a", "value":"10" }, { "group":"a", "value":"11" }, { "group":"b", "value":"2" }, { "group":"b", "value":"3" } ] 或者作为一张桌子,让
[
{
"group":"a",
"value":"10"
},
{
"group":"a",
"value":"11"
},
{
"group":"b",
"value":"2"
},
{
"group":"b",
"value":"3"
}
]
或者作为一张桌子,让它更容易阅读
group value
a 10
a 11
b 2
b 3
我想按组
进行排名,以获得
group value rank
a 10 1
a 11 2
b 2 1
b 3 2
在其他语言中,我会使用一个计数器循环遍历数据,当出现新的组值时,计数器会重置。我可以查看数据,但无法让计数器工作。在下面的示例中,似乎在下一次迭代中没有保留上一个计数器值,因此每个值都是1
{{ $counter := 1 }}
{{- range $index, $element := $data }}
{{ inline (gt $index 0) "," "" }}
{
"group" : "{{ .group }}",
"value" : "{{ .value }}",
"rank" : "{{ $counter }}"
{{ $counter := add $counter 1 }}
}
{{- end -}}
在显示例程中实现这种逻辑与go模板的设计理念背道而驰,并且通常违反了go模板的概念
也就是说,模板是一个显示(或“表示”)问题,而您在这里描述的排名是一个排序(或“业务逻辑”)问题。通过在显示组件中执行排序,您正在使程序变得脆弱,因为这些关注点不能相互独立地更改,也不能在一般意义上重用。例如,如果您想将元素打印为JSON或YAML数据,包括它们的排名,您必须重新实现您在文本模板中编写的排名逻辑;如果排名因某种原因而改变,那么你将不得不在多个地方进行更改
更好的方法是创建一个函数,根据需要对元素进行排序,而不依赖于如何显示它们。这样,您的程序在许多方面都更加健壮,主要是因为您只需要在项目更改时对项目进行排序,而不是每次显示项目时
例如():
类型项结构{
组字符串`json:“组”`
Value int`json:“值,字符串”`
Rank int`json:“秩,省略空”`
}
func main(){
//解析项目。
var项目[]项目
err:=json.Unmarshal([]字节(jsonstr),&items)
检查(错误)
//对项目进行排序。
RankItems(项目)
//显示项目。
打印表(项目)
PrintJSON(项目)
printyML(项目)//等。。。
}
func RankItems(xs[]项){
//按组、值对项目进行排序。
sort.Slice(xs,func(i,j int)bool{
x1,x2:=xs[i],xs[j]
如果x1.Group==x2.Group{
返回x1.值
数据来自何处以及存储在何种类型?更新了问题,存储在JSON中的数据可能与您手边的编程语言重复,您无需使用模板引擎,只需在执行模板之前对数据使用sort.sort
。
type Item struct {
Group string `json:"group"`
Value int `json:"value,string"`
Rank int `json:"rank,omitempty"`
}
func main() {
// Parse the items.
var items []Item
err := json.Unmarshal([]byte(jsonstr), &items)
check(err)
// Rank the items.
RankItems(items)
// Display the items.
PrintTable(items)
PrintJSON(items)
PrintYAML(items) // etc...
}
func RankItems(xs []Item) {
// Order the items by group, value.
sort.Slice(xs, func(i, j int) bool {
x1, x2 := xs[i], xs[j]
if x1.Group == x2.Group {
return x1.Value < x2.Value
}
return x1.Group < x2.Group
})
// Rank the items by position within a group.
var lastGroup string
var nextRank int
for i := range xs {
if i == 0 || lastGroup != xs[i].Group {
nextRank = 1
}
xs[i].Rank = nextRank
lastGroup = xs[i].Group
nextRank++
}
}