英文:
How to clear a map in Go?
问题
我正在寻找类似于C++函数.clear()
的东西,用于原始类型map
。
或者我应该只是创建一个新的map呢?
更新:谢谢你们的回答。通过看答案,我刚刚意识到有时候创建一个新的map可能会导致一些我们不想要的不一致性。考虑以下示例:
var a map[string]string
var b map[string]string
func main() {
a = make(map[string]string)
b=a
a["hello"]="world"
a = nil
fmt.Println(b["hello"])
}
我的意思是,这仍然不同于C++中的.clear()
函数,后者会清除对象中的内容。
英文:
I'm looking for something like the c++ function .clear()
for the primitive type map
.
Or should I just create a new map instead?
Update: Thank you for your answers. By looking at the answers I just realized that sometimes creating a new map may lead to some inconsistency that we don't want. Consider the following example:
var a map[string]string
var b map[string]string
func main() {
a = make(map[string]string)
b=a
a["hello"]="world"
a = nil
fmt.Println(b["hello"])
}
I mean, this is still different from the .clear()
function in c++, which will clear the content in the object.
答案1
得分: 156
你应该只是创建一个新的映射。没有真正的理由去尝试清除现有的映射,除非同一个映射被多个代码片段引用,并且其中一个片段明确需要清除值,以便其他代码片段能够看到这个变化。
所以,你应该只是这样写:
mymap = make(map[keytype]valtype)
如果你真的需要清除现有的映射,无论出于什么原因,这很简单:
for k := range m {
delete(m, k)
}
英文:
You should probably just create a new map. There's no real reason to bother trying to clear an existing one, unless the same map is being referred to by multiple pieces of code and one piece explicitly needs to clear out the values such that this change is visible to the other pieces of code.
So yeah, you should probably just say
mymap = make(map[keytype]valtype)
If you do really need to clear the existing map for whatever reason, this is simple enough:
for k := range m {
delete(m, k)
}
答案2
得分: 32
与C++不同,Go是一种垃圾回收的语言。你需要以稍微不同的方式思考。
当你创建一个新的映射时,
a := map[string]string{"hello": "world"}
a = make(map[string]string)
原始映射最终会被垃圾回收;你不需要手动清除它。但要记住,映射(和切片)是引用类型;你使用make()
来创建它们。只有当没有引用指向底层映射时,它才会被垃圾回收。
因此,当你执行以下操作时,
a := map[string]string{"hello": "world"}
b := a
a = make(map[string]string)
原始数组不会被垃圾回收(直到b被垃圾回收或b引用其他内容)。
英文:
Unlike C++, Go is a garbage collected language. You need to think things a bit differently.
When you make a new map
a := map[string]string{"hello": "world"}
a = make(map[string]string)
the original map will be garbage-collected eventually; you don't need to clear it manually. But remember that maps (and slices) are reference types; you create them with make()
. The underlying map will be garbage-collected only when there are no references to it.
Thus, when you do
a := map[string]string{"hello": "world"}
b := a
a = make(map[string]string)
the original array will not be garbage collected (until b is garbage-collected or b refers to something else).
答案3
得分: 11
Go 1.21
使用内置的clear
。
func main() {
m := map[string]int{"foo": 1}
clear(m)
}
这是一个单独的函数调用,并且具有一个次要但重要的优点,它将删除不可反射的键(有关此含义的详细信息,请参见下文)。标准库的maps
包不再具有maps.Clear
。
Go 1.18到1.20
您可以使用maps.Clear
。该函数属于golang.org/x/exp/maps
包(实验性质,不受兼容性保证的覆盖)。
> Clear从m中删除所有条目,使其为空。
示例用法:
func main() {
testMap := map[string]int{"gopher": 1, "badger": 2}
maps.Clear(testMap)
fmt.Println(testMap)
testMap["zebra"] = 2000
fmt.Println(testMap)
}
Playground: https://go.dev/play/p/qIdnGrd0CYs?v=gotip
如果您不想依赖实验性的包,可以复制粘贴源代码,它实际上非常简单:
func Clear[M ~map[K]V, K comparable, V any](m M) {
for k := range m {
delete(m, k)
}
}
重要提示:与内置的delete
一样,maps.Clear
的实现也不会从映射中删除不可反射的键。原因是对于不可反射的键,根据定义,x == x
为false。不可反射的键是NaN浮点数和任何其他支持比较运算符但包含NaN浮点数的类型。
请参考以下代码以了解其含义:
func main() {
m := map[float64]string{}
m[1.0] = "foo"
k := math.NaN()
fmt.Println(k == k) // false
m[k] = "bar"
maps.Clear(m)
fmt.Printf("len: %d, content: %v\n", len(m), m)
// len: 1, content: map[NaN:bar]
a := map[[2]float64]string{}
a[[2]float64{1.0, 2.0}] = "foo"
h := [2]float64{1.0, math.NaN()}
fmt.Println(h == h) // false
a[h] = "bar"
maps.Clear(a)
fmt.Printf("len: %d, content: %v\n", len(a), a)
// len: 1, content: map[[1 NaN]:bar]
}
Playground: https://go.dev/play/p/LWfiD3iPA8Q
英文:
Go 1.21
Use the builtin clear
.
func main() {
m := map[string]int{"foo": 1}
clear(m)
}
It's a single function call, and has the minor but important advantage that it will delete irreflexive keys (see below for details about what this means). The standard library maps
package doesn't have maps.Clear
anymore.
Go 1.18 to 1.20
You can use maps.Clear
. The function belongs to the package golang.org/x/exp/maps
(experimental and not covered by the compatibility guarantee)
> Clear removes all entries from m, leaving it empty.
Example usage:
func main() {
testMap := map[string]int{"gopher": 1, "badger": 2}
maps.Clear(testMap)
fmt.Println(testMap)
testMap["zebra"] = 2000
fmt.Println(testMap)
}
Playground: https://go.dev/play/p/qIdnGrd0CYs?v=gotip
If you don't want to depend on experimental packages, you can copy-paste the source, which is actually extremely simple:
func Clear[M ~map[K]V, K comparable, V any](m M) {
for k := range m {
delete(m, k)
}
}
IMPORTANT NOTE: just as with the builtin delete
— which the implementation of maps.Clear
uses —, this does not remove irreflexive keys from the map. The reason is that for irreflexive keys, by definition, x == x
is false. Irreflexive keys are NaN floats and every other type that supports comparison operators but contains NaN floats somewhere.
See this code to understand what this entails:
func main() {
m := map[float64]string{}
m[1.0] = "foo"
k := math.NaN()
fmt.Println(k == k) // false
m[k] = "bar"
maps.Clear(m)
fmt.Printf("len: %d, content: %v\n", len(m), m)
// len: 1, content: map[NaN:bar]
a := map[[2]float64]string{}
a[[2]float64{1.0, 2.0}] = "foo"
h := [2]float64{1.0, math.NaN()}
fmt.Println(h == h) // false
a[h] = "bar"
maps.Clear(a)
fmt.Printf("len: %d, content: %v\n", len(a), a)
// len: 1, content: map[[1 NaN]:bar]
}
Playground: https://go.dev/play/p/LWfiD3iPA8Q
答案4
得分: 10
// 方法一,假设book是一个map的名称
for k := range book {
delete(book, k)
}
// 方法二
book = make(map[string]int)
// 方法三
book = map[string]int{}
英文:
// Method - I , say book is name of map
for k := range book {
delete(book, k)
}
// Method - II
book = make(map[string]int)
// Method - III
book = map[string]int{}
答案5
得分: 1
for k := range m {
delete(m, k)
}
只有当m
不包含任何包含NaN
的键值时才有效。
delete(m, k)
对于任何__非自反键__(例如math.NaN()
)都不起作用,也不适用于包含任何NaN
浮点数的结构体或其他可比较类型。给定具有NaN
值的struct{ val float64 }
也是非自反的(引用自blackgreen的评论)
为了解决这个问题并支持在Go中清除地图,可以在新版本中提供一个内置的clear(x)
函数,详细信息请参考add clear(x) builtin, to clear map, zero content of slice, ptr-to-array
> 新函数clear从地图中删除所有元素或将切片的所有元素设置为T的零值。
调用 | 参数类型 | 结果 |
---|---|---|
clear(m) | map[K]T | 删除所有条目,使地图为空(len(m) == 0) |
clear(s) | []T | 将所有元素设置为T的零值,直到s的长度 |
clear(t) | 类型参数 | 参见下文 |
如果clear的参数类型是类型参数,则其类型集中的所有类型必须是地图或切片,并且clear执行与实际类型参数对应的操作。
如果地图或切片为nil,则clear不执行任何操作。
英文:
For the method of clearing a map in Go
for k := range m {
delete(m, k)
}
It only works if m
contains no key values containing NaN
.
delete(m, k)
doesn't work for any irreflexive key (such as math.NaN()
), but also structs or other comparable types with any NaN
float in it. Given struct{ val float64 }
with NaN
val is also irreflexive (Quote by blackgreen comment)
To resolve this issue and support clearing a map in Go, one buildin clear(x)
function could be available in the new release, for more details, please refer to add clear(x) builtin, to clear map, zero content of slice, ptr-to-array
> The new function clear deletes all elements from a map or zeroes all elements of a slice.
Call | Argument type | Result |
---|---|---|
clear(m) | map[K]T | deletes all entries, resulting in an empty map (len(m) == 0) |
clear(s) | []T | sets all elements up to the length of s to the zero value of T |
clear(t) | type parameter | see below |
If the type of the argument to clear is a type parameter, all types in its type set must be maps or slices, and clear performs the operation corresponding to the actual type argument.
If the map or slice is nil, clear is a no-op.
答案6
得分: 0
Go 1.21 Release 添加了三个新的内置函数到语言中。特别是:
- 新的函数 clear 用于删除映射中的所有元素或将切片的所有元素置零。
它的使用方法如下:
m := map[string]string{"hello": "world"}
clear(m)
fmt.Println(m) // map[]
https://go.dev/play/p/UdQBUEeQ4ck?v=gotip
英文:
Go 1.21 Release adds three new built-ins to the language. In particular:
- The new function clear deletes all elements from a map or zeroes all elements of a slice.
It works like that:
m := map[string]string{"hello": "world"}
clear(m)
fmt.Println(m) // map[]
答案7
得分: -8
如果您正在尝试在循环中执行此操作,您可以利用初始化来清除地图。例如:
for i:=0; i<2; i++ {
animalNames := make(map[string]string)
switch i {
case 0:
animalNames["cat"] = "Patches"
case 1:
animalNames["dog"] = "Spot";
}
fmt.Println("对于地图实例", i)
for key, value := range animalNames {
fmt.Println(key, value)
}
fmt.Println("-----------\n")
}
当您执行此操作时,它会清除先前的地图并从空地图开始。这通过输出进行验证:
$ go run maptests.go
对于地图实例 0
cat Patches
-----------
对于地图实例 1
dog Spot
-----------
英文:
If you are trying to do this in a loop, you can take advantage of the initialization to clear out the map for you. For example:
for i:=0; i<2; i++ {
animalNames := make(map[string]string)
switch i {
case 0:
animalNames["cat"] = "Patches"
case 1:
animalNames["dog"] = "Spot";
}
fmt.Println("For map instance", i)
for key, value := range animalNames {
fmt.Println(key, value)
}
fmt.Println("-----------\n")
}
When you execute this, it clears out the previous map and starts with an empty map. This is verified by the output:
$ go run maptests.go
For map instance 0
cat Patches
-----------
For map instance 1
dog Spot
-----------
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论