英文:
Insert objects in specific order with map
问题
我有一个使用案例,其中对象的顺序需要按特定顺序排列。当前的实现是使用map
,我找到了许多帖子和文章,其中指出map
是一个无序列表。我找到的所有解决方案都是将键设置为整数,并使用sort.Ints(keys)
按键排序。
在代码中,我使用一个yaml模板来实例化一个字典对,然后将其传递给ProcessFruits函数进行逻辑处理。
我该如何获得期望的结果(见下文),即始终将fruits.yml.tmpl中列表顶部的对象放在第一位?
这是我代码的简化版本:
//文件名:fruits.yml.tmpl
fruits: {{ $fruits := processFruits
"oranges" true
"bananas" false
"apples" true
}}
{{ $fruits }}
//文件名:fruits.go
func ProcessFruits(fruits map[string]interface{}) (interface{}) {
keys := make([]string, len(fruits))
i := 0
for fruit := range fruits {
keys[i] = fruit
i++
}
sort.Strings(keys)
fmt.Println(keys)
}
//将fruits.yml.tmpl连接到ProcessFruits函数
tmpl, err := template.New(t).Funcs(template.FuncMap(map[string]interface{}{
"processFruits": ProcessFruits,
})).Funcs(sprig.TxtFuncMap())
实际结果:
[apples:true bananas:false oranges:true]
期望结果:
[oranges:true bananas:false apples:true]
Go Playground
https://go.dev/play/p/hK2AdRVsZXJ
英文:
I have a use case where the order of objects needs to be in a specific order. The current implementation is done with using map
and I've found numerous posts and articles where it states that map
are an unordered list. All of the solutions that I found are those where they've made the keys as integers and they've used sort.Ints(keys)
to sort by keys.
In the code, I'm using a yaml template to instantiate a dictionary pair, then passing it into the ProcessFruits function where it does the logic.
How would I go about getting the desired result (see below) where the object from the top of the list in fruits.yml.tmpl will always be first?
Here's a simplified version of my code:
//Filename: fruits.yml.tmpl
fruits: {{ $fruits := processFruits
"oranges" true
"bananas" false
"apples" true
}}
{{ $fruits }}
//Filename: fruits.go
func ProcessFruits(fruits map[string]interface{}) (interface{}) {
keys := make([]string, len(fruits))
i := 0
for fruit := range fruits {
keys[i] = fruit
i++
}
sort.Strings(keys)
fmt.Println(keys)
}
// Connect fruits.yml.tmpl to the ProcessFruits function
tmpl, err := template.New(t).Funcs(template.FuncMap(map[string]interface{}{
"processFruits": ProcessFruits,
})).Funcs(sprig.TxtFuncMap())
Actual Results:
[apples:true bananas:false oranges:true]
Desired Results:
[oranges:true bananas:false apples:true]
Go Playground
答案1
得分: 0
你错过了使用sort.Reverse()和sort.StringSlice()的用法。
func main() {
keys := []string{"bananas", "apples", "oranges"}
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
fmt.Println(keys)
}
你可以在这个链接中查看代码示例:https://go.dev/play/p/n08S7xtbeij
更多信息请参考:https://pkg.go.dev/sort#example-Reverse
英文:
You are missing the usage of sort.Reverse() and sort.StringSlice()
func main() {
keys := []string{"bananas", "apples", "oranges"}
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
fmt.Println(keys)
}
答案2
得分: 0
参数作为切片传递。将每隔一个参数作为字符串收集起来并打印:
func ProcessFruits(args ...interface{}) interface{} {
var fruits []string
for i, arg := range args {
if i%2 == 0 {
fruits = append(fruits, arg.(string))
}
}
fmt.Println(fruits)
return nil
}
英文:
The arguments are passed as a slice. Collect every other argument as a string and print:
func ProcessFruits(args ...interface{}) interface{} {
var fruits []string
for i, arg := range args {
if i%2 == 0 {
fruits = append(fruits, arg.(string))
}
}
fmt.Println(fruits)
return nil
}
答案3
得分: 0
不是最漂亮的解决方案,但我想我已经找到了一个解决我的问题的可行代码。我所做的是创建另一个字典来跟踪“水果”的顺序,然后使用嵌套的for循环将这两个字典合并在一起,并将结果输出到一个切片中。
这是我的代码:
package main
import (
"fmt"
"sort"
)
func ProcessFruits(fruits map[string]interface{}, counts map[int]string) {
keys := make([]string, len(fruits))
var foo []string
var baz []int
for k := range fruits {
foo = append(foo, k)
}
for _, k := range foo {
fmt.Println("键-字符串:", k, "值-布尔:", fruits[k])
}
fmt.Println("==========================")
// 遍历计数(键是整数)
for l := range counts {
baz = append(baz, l)
}
sort.Ints(baz)
for _, l := range baz {
fmt.Println("键-整数:", l, "值-字符串:", counts[l])
}
fmt.Println("==========================")
// 将具有排序后的整数键的列表与包含真/假的其他列表相关联
i := 0
for _, m := range baz {
for _, n := range foo {
//fmt.Println("键-整数:", m, "值-字符串:", counts[m])
//fmt.Println("键-字符串:", n, "值-布尔:", fruits[n])
if counts[m] == n {
keys[i] = n
i++
//fmt.Println(i)
}
}
}
// 所需结果现在在切片keys中。
fmt.Println(keys)
}
func main() {
var m = map[string]interface{}{
"oranges": true,
"bananas": false,
"apples": true,
}
var n = map[int]string{
0: "oranges",
1: "bananas",
2: "apples",
}
ProcessFruits(m, n)
}
如果有更好的解决方案,我会很好奇知道。
英文:
Not the prettiest solution, but I think I've figured out a working code to my problem. What I've done was creating another dictionary that will keep track of the order of the "fruits", then combining the two dictionary together with a nested for loop and output the result to a slice.
Here's my code:
package main
import (
"fmt"
"sort"
)
func ProcessFruits(fruits map[string]interface{}, counts map[int]string) {
keys := make([]string, len(fruits))
var foo []string
var baz []int
for k := range fruits {
foo = append(foo, k)
}
for _, k := range foo {
fmt.Println("Key-string:", k, "Value-bool:", fruits[k])
}
fmt.Println("==========================")
// Iterate over counts (keys are ints)
for l := range counts {
baz = append(baz, l)
}
sort.Ints(baz)
for _, l := range baz {
fmt.Println("Key-int:", l, "Value-string:", counts[l])
}
fmt.Println("==========================")
// Correlate list with sorted integer keys with the other list that contains true/false
i := 0
for _, m := range baz {
for _, n := range foo {
//fmt.Println("Key-int:", m, "Value-string:", counts[m])
//fmt.Println("Key-string:", n, "Value-bool:", fruits[n])
if counts[m] == n {
keys[i] = n
i++
//fmt.Println(i)
}
}
}
// Desired results is now in the slice, keys.
fmt.Println(keys)
}
func main() {
var m = map[string]interface{}{
"oranges": true,
"bananas": false,
"apples": true,
}
var n = map[int]string{
0: "oranges",
1: "bananas",
2: "apples",
}
ProcessFruits(m, n)
}
If anyone has a better solution, then I'd be curious to know.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论