首页 >后端开发 >Golang >迭代 Go Map 时如何保持插入顺序?

迭代 Go Map 时如何保持插入顺序?

Patricia Arquette
Patricia Arquette原创
2024-12-20 00:29:09850浏览

How to Maintain Insertion Order When Iterating Through a Go Map?

按插入顺序循环遍历 Map

Go 中的 Map 不保证迭代顺序,当您想要检索项目时,这可能会令人沮丧按照它们插入的顺序。虽然存在一些解决方法,但它们通常涉及使用单独的切片或创建数据重复,这可能会导致复杂性和潜在的错误。

使用键切片的解决方案

一个可行的解决方案解决方案是按插入顺序维护一个键片。当向映射添加新对时,首先检查该键是否存在于切片中。如果没有,请将密钥附加到切片中。迭代时,只需使用切片按顺序检索键并从映射中访问相应的值即可。这种方法的开销最小,因为切片仅存储键。

示例:

type Key int
type Value int

type OrderedMap struct {
    m    map[Key]Value
    keys []Key
}

func NewOrderedMap() *OrderedMap {
    return &OrderedMap{m: make(map[Key]Value)}
}

func (om *OrderedMap) Set(k Key, v Value) {
    if _, ok := om.m[k]; !ok {
        om.keys = append(om.keys, k)
    }
    om.m[k] = v
}

func (om *OrderedMap) Range() {
    for _, k := range om.keys {
        fmt.Println(om.m[k])
    }
}

使用值包装器链接列表的解决方案

或者,您可以将值包装在链表结构中。每个值包装器都包含实际值和指向列表中下一个键的指针。添加新对时,将前一个值包装器的下一个指针设置为指向新键。迭代时,从第一个键开始,按照 next 指针按顺序检索值。

示例:

type Key int
type Value int

type ValueWrapper struct {
    v    Value
    next *Key
}

type OrderedMap struct {
    m           map[Key]ValueWrapper
    first, last *Key
}

func NewOrderedMap() *OrderedMap {
    return &OrderedMap{m: make(map[Key]ValueWrapper)}
}

func (om *OrderedMap) Set(k Key, v Value) {
    if _, ok := om.m[k]; !ok && om.last != nil {
        pw2 := om.m[*om.last]
        om.m[*om.last] = ValueWrapper{pw2.v, &k}
    }
    pw := ValueWrapper{v: v}
    om.m[k] = pw
    if om.first == nil {
        om.first = &k
    }
    om.last = &k
}

func (om *OrderedMap) Range() {
    for k := om.first; k != nil; {
        pw := om.m[*k]
        fmt.Println(pw.v)
        k = pw.next
    }
}

比较

关键切片方法更简单,但元素删除效率较低,因为它需要在切片中进行线性搜索。值包装链表方法允许快速删除元素,使其更适合需要频繁删除的情况。

最终,最佳选择取决于您应用程序的具体要求。

以上是迭代 Go Map 时如何保持插入顺序?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn