检查不同的Go map类型中是否存在重复的键。

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

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
}

playground

英文:

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
}

playground

huangapple
  • 本文由 发表于 2023年2月10日 14:35:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75407664.html
匿名

发表评论

匿名网友

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

确定