使用地图按特定顺序插入对象

Insert objects in specific order with map

我有一个用例,其中对象的顺序需要按特定顺序排列。当前的实现是使用 map 完成的,我发现许多帖子和文章都指出 map 是一个无序列表。我找到的所有解决方案都是将键作为整数并使用 sort.Ints(keys) 按键排序的解决方案。

在代码中,我使用 yaml 模板来实例化字典对,然后将其传递到执行逻辑的 ProcessFruits 函数中。

如果 fruits.yml.tmpl 中列表顶部的对象始终排在第一位,我将如何获得所需的结果(见下文)?

这是我的代码的简化版本:

//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())

实际结果:

[apples:true bananas:false oranges:true]

期望的结果:

[oranges:true bananas:false apples:true]

去游乐场

https://go.dev/play/p/hK2AdRVsZXJ

您缺少 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

参数作为切片传递。将所有其他参数收集为字符串并打印:

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
}

不是最漂亮的解决方案,但我想我已经找到了解决我的问题的有效代码。我所做的是创建另一个字典来跟踪“水果”的顺序,然后将两个字典与嵌套的 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("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)

}

如果有人有更好的解决方案,那么我很想知道。