generic function to convert Map to List in GO

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

generic function to convert Map to List in GO

问题

你好!以下是你要翻译的内容:

如何在Go中编写一个函数,将任何Map转换为对象列表(丢弃键)?

例如:

func mapToList(inputMap map[any]any) any {
    var resultList []any 
    for _, obj := range inputMap {
        resultList = append(resultList, obj)
    }
    return resultList
}

func main() {
	myMap := make(map[string]string)
	myMap["a"] = "1"
	myMap["b"] = "12"
	l := mapToList(myMap).([]string)
    fmt.Printf("(%v, %T)\n", l, l)
}

输出结果应为:([1 12], []string)

但是我总是遇到类型问题,找不到解决方法。使用类型断言或转换时,我遇到了类似的问题。

cannot use myMap (variable of type map[string]string) as map[any]any value in argument to mapToList

我应该如何编写mapToList()函数?

它必须以inputMap map[any]anyinputMap any作为输入,因为我想传入任何类型的映射(map[string]CustomStruct; map[int][]CustomStruct等)。

更新:我已经添加了我最初编写的函数以及更多关于输入的细节。

英文:

How can I write a function in Go that would convert any Map to a List of object (dropping the keys) ?

For instance:

func mapToList(inputMap map[any]any) any {
    var resultList []any 
    for _, obj := range inputMap {
        resultList = append(resultList, obj)
    }
    return resultList
}

func main() {
	myMap := make(map[string]string)
	myMap["a"] = "1"
	myMap["b"] = "12"
	l := mapToList(myMap).([]string)
    fmt.Printf("(%v, %T)\n", l, l)
}

would output: ([1 12], []string)

But I always run into a type issue and didn't find a way around. Using type assertion or conversion I run into the similar issue.

cannot use myMap (variable of type map[string]string) as map[any]any value in argument to mapToList

How should I write the mapToList() function ?

It must take as an input inputMap map[any]any or inputMap any because I want to pass in any kind of map (map[string]CustomStruct; map[int][]CustomStruct, etc.)

Update: I added the function as I first write it and more more details on the input

答案1

得分: 1

参见泛型的教程语言规范

any不是变量类型,它是一个类型约束,描述了可以使用的类型。您需要使用约束any定义类型参数,然后在参数签名中引用泛型类型。

//                                 | 从这一点开始,K和V是
//                                 | 可以在函数中使用的有效类型
func mapToSlice[K comparable, V any](m map[K]V) []V {
    s := make([]V, 0, len(m))
    for _, v := range m {
        s = append(s, v)
    }
    return s
}

参数m必须是map[K]V类型,其中Kcomparable类型,Vany类型。返回类型[]V将是与输入映射中的值类型相同的切片类型。

请注意,any不能用作映射键的约束,因为并非所有类型都可以用作键,只有comparable类型可以。

然后,要调用该方法,您需要传入满足约束条件的类型(例如map[string][]string),可以选择显式指定类型参数。

m := map[string][]string{
    "A": {"B", "C"},
    "D": {"E", "F"},
}
s := mapToSlice(m)
// 或者
t := mapToSlice[string, []string](m)
// [[B C] [E F]]

通过显式指定类型,您可以自我记录代码,并捕获任何意外的类型问题。例如,以下代码将返回错误:

v := mapToSlice[string, []int](m)
...
./main.go:14:33: cannot use m (variable of type map[string][]string) as map[string][]int value in argument to mapToSlice[string, []int]
英文:

See this tutorial on Generics or the language spec

any is not the variable type, it is a type constraint, a description of the types that can be used. You need to define the type parameters with the constraint any, and then reference the generic types from within the parameter signatures.

//                                 | from this point on, K and V are
//                                 | now valid types to use in the function
func mapToSlice[K comparable, V any](m map[K]V) []V {
	s := make([]V, 0, len(m))
	for _, v := range m {
		s = append(s, v)
	}
	return s
}

The parameter m must be map[K]V, where K is a comparable type and V is any type. The return type []V will be a slice of the same type used for the values in the input map.

Note that any can't be used as the constraint for the keys of the map, since not all types can be used as keys, only comparable types.

Then to call the method, you pass in a type that satisfies the constraints (eg map[string][]string), optionally making explicit the type parameters.

m := map[string][]string{
	"A": {"B", "C"},
	"D": {"E", "F"},
}
s := mapToSlice(m)
// or
t := mapToSlice[string, []string](m)
// [[B C] [E F]]

By making the type explicit, you can self-document your code and also catch any accidental type issues. For example, the following code will return an error:

v := mapToSlice[string, []int](m)
...
./main.go:14:33: cannot use m (variable of type map[string][]string) as map[string][]int value in argument to mapToSlice[string, []int]

huangapple
  • 本文由 发表于 2023年2月20日 23:43:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75511367.html
匿名

发表评论

匿名网友

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

确定