英文:
Check duplicated keys in different go map types
问题
我想要一个函数来检查不同地图中的重复键。
这是我目前的代码:
ma := map[string]typeA
mb := map[string]typeB
mc := map[string]typeC
dup := map[string]bool{}
for k := range ma {
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
for k := range mb {
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
for k := range mc {
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
return nil
我想要重构这段代码,并编写一个函数:
func checkDupKeys[M ~map[K]V, K comparable, V any](maps ...M) error {
dup := map[K]bool{}
for _, m := range maps {
for k := range m {
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
}
return nil
}
但是它只能接受具有相同类型的地图,而不能接受typeA、typeB和typeC。
英文:
I want to have a function to check duplicated keys in different maps.
This is what I have
ma := map[string]typeA
mb := map[string]typeB
mc := map[string]typeC
dup := map[string]bool{}
for k := range ma{
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
for k := range mb{
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
for k := range mc {
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
return nil
I want to refactor this and I write a function
func checkDupKeys[M ~map[K]V, K comparable, V any](maps ...M) error {
dup := map[K]bool{}
for _, m := range maps {
for k := range m {
if !dup[k] {
dup[k] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
}
return nil
}
But It can only accept maps with the same type, not typeA, typeB and typeC.
答案1
得分: 2
你可以尝试使用any
类型和反射。
func checkDupKeys(maps ...any) error {
dup := map[any]bool{}
for i, m := range maps {
t := reflect.TypeOf(m)
if t.Kind() != reflect.Map {
return fmt.Errorf("不是一个映射,在索引位置:%d", i)
}
keys := reflect.ValueOf(m).MapKeys()
for _, k := range keys {
v := k.Interface()
if !dup[v] {
dup[v] = true
} else {
return fmt.Errorf("重复的键[%v]", v)
}
}
}
return nil
}
这种方法的缺点是该函数也会接受非映射类型的参数,而编译器不会对此发出警告。
英文:
You can try using any
type and reflection
func checkDupKeys(maps ...any) error {
dup := map[any]bool{}
for i, m := range maps {
t := reflect.TypeOf(m)
if t.Kind() != reflect.Map {
return fmt.Errorf("not a map at index: %d", i)
}
keys := reflect.ValueOf(m).MapKeys()
for _, k := range keys {
v := k.Interface()
if !dup[v] {
dup[v] = true
} else {
return fmt.Errorf("duplicate key[%v]", v)
}
}
}
return nil
}
Disadvantage of this approach is the fact that this function will also accept non-map arguments and compiler will not warn you about this.
答案2
得分: 1
如果我想要实现这个函数,我会选择不同的方法。
package main
import (
"fmt"
"reflect"
)
func main() {
ma := map[string]int{"one": 1, "two": 2}
mb := map[string]string{"one": "one"}
mc := map[string]float64{"one": 1.1}
fmt.Println(checkDupKeys(ma, mb, mc))
}
func checkDupKeys(maps ...interface{}) error {
dup := map[string]bool{}
for _, m := range maps {
v := reflect.ValueOf(m).MapKeys()
for _, k := range v {
if !dup[k.Interface().(string)] {
dup[k.Interface().(string)] = true
} else {
return fmt.Errorf("重复的键[%v]", k)
}
}
}
return nil
}
英文:
If I wanted to implement that function, I would chose a different approach
package main
import (
"fmt"
"reflect"
)
func main() {
ma := map[string]int{"one": 1, "two": 2}
mb := map[string]string{"one": "one"}
mc := map[string]float64{"one": 1.1}
fmt.Println(checkDupKeys(ma, mb, mc))
}
func checkDupKeys(maps ...any) error {
dup := map[string]bool{}
for _, m := range maps {
v := reflect.ValueOf(m).MapKeys()
for _, k := range v {
if !dup[k.Interface().(string)] {
dup[k.Interface().(string)] = true
} else {
return fmt.Errorf("duplicate key[%v]", k)
}
}
}
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论