GO:从地图弹出

时间:2014-02-25 18:58:24

标签: dictionary go pop

是否存在可以从GO中的地图中弹出(键,值)对的现有函数?我使用pop而不是remove,因为pop会在删除(key,value)的索引之后重新排列元素。

以下代码为例:

package main

import "fmt"

func main() {
    mapp := make(map[int]int)
    fmt.Println("before removal:")

    for i := 1; i < 7; i++ {
        mapp[i] = i
    }
    fmt.Println(mapp)
    delete(mapp, 2)
    fmt.Println("\nafter the removal:")
    for i := 1; i < 7; i++ {
        fmt.Println(i, mapp[i])
    }

}

产生以下输出:

before removal:
map[1:1 2:2 3:3 4:4 5:5 6:6]

after the removal:
1 1
2 0
3 3
4 4
5 5
6 6

我们注意到索引位置2为空。我希望输出如下:

before removal:
map[1:1 2:2 3:3 4:4 5:5 6:6]

after the removal:
1 1
2 3
3 4
4 5
5 6

此功能是否已经在GO中,或者我是否必须实施它?

谢谢!

2 个答案:

答案 0 :(得分:3)

我认为你误解了map是什么以及它是如何运作的。你不应该把它看作是一个“有差距的数组”,而是作为一个经典的hash table

要回答您的问题,当您使用delete()时,该值会从map中删除,问题在于您如何迭代地图的“值”。

为了帮助您理解:

mapp := make(map[int]int)
fmt.Println(2, mapp[2])

将打印

2 0

为什么?仅仅因为当请求的密钥不存在时,我们得到值类型的零值。在这种情况下,值类型为int,因此零值为0.

因此,您希望在打印之前查看地图中是否存在密钥,并且必须使用双值赋值,如下所示:

for i := 1; i < 7; i++ {
    if value, exists := mapp[i]; exists {
        fmt.Println(i, value)
    }
}

它会打印

1 1
3 3
4 4
5 5
6 6

不是你想要的,但你可以直接用map获得。 您可以查看this blog post以获取更多信息和示例。

如果您真的想要一个可以删除值的数组,请参阅Verran的答案并改为使用切片。

答案 1 :(得分:2)

来自Go documentation

When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next.

由此可见,无法自动将值向上移动一个位置以填充间隙,因为每次查看值时,键都可以位于不同的迭代位置,并且不能保证映射到2的值将向上滑动到1

如果您想要执行此类操作,则必须手动将所有内容移至一个键值,例如:

for key := 2; key < len(map)-1; key++ {
    map[key] = map[key+1]
}

或者,您可以使用切片,如果您知道需要“弹出”的索引,请创建一个省略该值的新切片:

value := slice[2]
slice = copy(slice[:2], slice[2+1:])