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

发布于 01-09 07:46 字数 1281 浏览 1 评论 0原文

我有一个用例,其中对象的顺序需要按特定顺序。当前的实现是使用 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:truebananas:falseoranges:true]

期望结果:

[oranges:truebananas:falseapples: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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

意中人2025-01-16 07:46:52

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

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

See: https://pkg.go.dev/sort#example-Reverse

左秋2025-01-16 07:46:52

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

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
}
⊕婉儿2025-01-16 07:46:52

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

}

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文