Golang中Sorted maps和slices每次编译结果不同如何解决

Golang中Sorted maps和slices每次编译结果不同如何解决 大家好,

有人能帮我理解一下下面这段代码是怎么回事吗?我不明白为什么每次运行它都会得到不同的结果。我的目标是创建一个映射(map)并按键排序,然后我想将其值收集到一个切片(slice)中。

package main

import (
    "fmt"
    "sort"
)

func main() {
    map1 := make(map[uint16][]byte)
    map1[264] = []byte{4, 6, 2, 7}
    map1[85] = []byte{99, 65, 4, 11, 22}
    map1[668] = []byte{44, 25, 47, 23, 72, 63, 48}
    map1[32] = []byte{19, 63, 40}
    fmt.Println(map1)
    keys := make([]uint16, 0)
    for key := range map1 {
        keys = append(keys, key)
    }
    fmt.Println("keys: ", keys)
    sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
    fmt.Println("sorted keys: ", keys)
    sort_map := make(map[uint16][]byte)
    for k := range keys {
        sort_map[keys[k]] = map1[keys[k]]
    }
    fmt.Println(sort_map)
    for k, v := range sort_map {
        fmt.Println(k, v)
    }
    total_data := make([]byte, 0)
    for _, v := range sort_map {
        total_data = append(total_data, v...)
    }
    fmt.Println(total_data)
    for i := range total_data {
        x := total_data[i]
        fmt.Println(x)
    }
}

非常感谢您的帮助,我真的很感激。


更多关于Golang中Sorted maps和slices每次编译结果不同如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

是的,非常感谢您的帮助

更多关于Golang中Sorted maps和slices每次编译结果不同如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Map 是不可排序的。你可以改为对键的切片进行排序,就像你已经在做的那样,然后每当需要按顺序获取数据时,就遍历该切片。

我不太确定我理解你想要做什么,但我移除了 sort_map 并想出了这个。这是你想要的吗?

非常感谢您的快速回复。我已经按照您说的做了,但不知道为什么每次编译都会得到不同的结果。

这个结果是正确的

Capture d’écran de 2023-03-29 14-32-21

而这两个结果是不正确的。

Capture d’écran de 2023-03-29 14-31-22 Capture d’écran de 2023-03-29 14-31-48

在Go语言中,map的迭代顺序是非确定性的,这是设计上的特性。你遇到的问题根源在于:虽然你创建了排序后的键切片,但在填充sort_map时,仍然使用了for k := range keys这种顺序迭代,这本身是确定性的。然而,问题出在最后遍历sort_map,你使用了for _, v := range sort_map,这又会回到map的非确定性迭代上。

以下是修改后的代码,关键点在于:直接使用已排序的键切片来访问值,而不是再次遍历map

package main

import (
    "fmt"
    "sort"
)

func main() {
    map1 := make(map[uint16][]byte)
    map1[264] = []byte{4, 6, 2, 7}
    map1[85] = []byte{99, 65, 4, 11, 22}
    map1[668] = []byte{44, 25, 47, 23, 72, 63, 48}
    map1[32] = []byte{19, 63, 40}
    
    // 提取并排序键
    keys := make([]uint16, 0, len(map1))
    for key := range map1 {
        keys = append(keys, key)
    }
    sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
    
    // 直接使用排序后的键来构建有序切片
    total_data := make([]byte, 0)
    for _, key := range keys {
        total_data = append(total_data, map1[key]...)
    }
    
    fmt.Println("Sorted keys:", keys)
    fmt.Println("Total data (in order of sorted keys):", total_data)
    
    // 如果需要验证,按顺序打印
    for _, key := range keys {
        fmt.Printf("Key %d: %v\n", key, map1[key])
    }
}

如果你确实需要一个保持插入顺序的map结构,可以使用第三方库如github.com/elliotchance/orderedmap,但针对你的需求,直接使用排序后的键切片访问原始map是最简洁的方案。

回到顶部