从地图中弹出(删除)一个元素。

huangapple go评论77阅读模式
英文:

Go: pop from a map

问题

在Go语言中,没有直接的函数可以从map中弹出(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)
	pop(mapp, 2)
	fmt.Println("\nafter the removal:")
	for i := 1; i < 7; i++ {
		fmt.Println(i, mapp[i])
	}

}

func pop(m map[int]int, key int) {
	delete(m, key)
	for i := key + 1; i <= len(m)+1; i++ {
		if val, ok := m[i]; ok {
			delete(m, i)
			m[i-1] = val
		}
	}
}

这段代码定义了一个名为pop的函数,它接受一个map和一个key作为参数。函数首先删除指定的key,然后重新排列剩余的元素,使得map中的key连续。通过调用pop函数,你可以实现从map中弹出(key,value)对的功能。

希望对你有帮助!

英文:

Is there an existing function where we can pop a (key,value) pair from a map in GO? I use the word pop instead of remove because a pop would re-arrange the elements after the index where the (key,value) was removed.

As an example the following code:

package main

import &quot;fmt&quot;

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

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

}

Produces the following output:

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

We notice that index location 2 is empty. I would like the output to be the following:

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

Is this functionality already in Go or would I have to implement it?

答案1

得分: 4

我认为你对map的理解有误,以及它的工作原理。你不应该将它看作是一个"有间隔的数组",而应该看作是一个经典的哈希表

回答你的问题,当你使用delete()时,该值会从map中删除,问题在于如何迭代遍历map的"值"。

为了帮助你理解:

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

将会打印出

2 0

为什么呢?因为当请求的键不存在时,我们会得到值类型的零值。在这种情况下,值类型是int,所以零值是0。

所以,在打印之前,你想要检查一个键是否存在于map中,并且你必须使用两个值的赋值,像这样:

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获得的最接近的结果。
你可以查看这篇博文获取更多信息和示例。

如果你真的想要一个可以删除值的数组,请参考Verran的回答,并使用切片代替。

英文:

I think that you are misunderstanding what a map is and how it works. You should not see it as an "array with gaps", but as a classic hash table.

And to answer your question, when you use delete(), the value is deleted from the map, the problem is how you iterate over the "values" of the map.

To help you understand:

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

will print

2 0

Why ? Simply because when the requested key doesn't exist, we get the value type's zero value. In this case the value type is int, so the zero value is 0.

So, you want to see if a key exists in the map before printing it and you have to use two-value assignment, like that:

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

and it will print

1 1
3 3
4 4
5 5
6 6

Not really what you want, but the closer you can get directly with maps.
You can have a look at this blog post for more information and examples.

If you really want to have an array where you can remove values, see Verran's answer and use slices instead.

答案2

得分: 2

根据Go文档的说明:

在使用range循环迭代map时,迭代顺序是不确定的,不能保证每次迭代时的顺序都相同。

由此可见,没有办法自动将一个值向上移动一个位置来填补空缺,因为每次查看值时,键可能处于不同的迭代位置,并且不能保证映射到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:])
英文:

From the 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.

From this, it follows that there would be no way to automatically move a value up one position to fill a gap, since the key can be in a different iteration position each time you look at the values and theres no guarantee that the value mapped to 2 will slide up to 1.

If you want to do something like this, you will have to manually shift everything down one key value, something like:

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

Alternatively, you could use slices and if you know the index you need to "pop", create a new slice that omits the value:

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

huangapple
  • 本文由 发表于 2014年2月26日 02:58:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/22023633.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定