我在json中有一些数据
[
{
"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
排名
group value rank
a 10 1
a 11 2
b 2 1
b 3 2
在其他语言中,我会使用一个计数器循环数据,当有一个新的group
值时,该计数器会重置。我可以通过数据,但我不能让计数器工作。在下面的例子中,似乎前一个计数器值没有保留在下一次迭代中,因此每个值都是1.
{{ $counter := 1 }}
{{- range $index, $element := $data }}
{{ inline (gt $index 0) "," "" }}
{
"group" : "{{ .group }}",
"value" : "{{ .value }}",
"rank" : "{{ $counter }}"
{{ $counter := add $counter 1 }}
}
{{- end -}}
答案 0 :(得分:0)
在显示例程中实现这种逻辑与go模板的设计原理相反,并且通常违反separation of concerns的概念。
也就是说,模板是 display (或“表示”)关注点,而如您在此处描述的那样,排名是 ordering (或“业务逻辑”)关注点。通过在显示组件中执行排序,您使程序变得脆弱,因为这些顾虑不能彼此独立地更改,也不能在一般意义上重复使用。例如,如果要将元素打印为JSON或YAML数据(包括其排名),则必须重新实现在文本模板中编写的排名逻辑;如果排名由于某种原因发生了变化,那么您将不得不在多个位置进行更改。
更好的方法是创建一个功能,以按需排列元素,而与您如何显示它们无关。这样,您的程序可以在许多方面更强大,主要是因为您只需要在项目更改时才对其进行排名,而不是每次显示它们时都需要对其进行排名。
例如(Go Playground):
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++
}
}