Go map 转 slice

Posted 恋喵大鲤鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go map 转 slice相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

编码中,我们可能需要将 map 的 key 或者 value 转换为 slice 进行操作。

面对具体类型 map 如 map[string]string,我们很容易写出下面的转换函数。

// Map2StrSlice converts the key and value of map to string slice
func Map2StrSlice(m  map[string]string)([]string, []string) {
	slK, slV := make([]string, 0, len(m)), make([]string, 0, len(m))
	for k, v := {
		slK = append(slK, k)
		slV = append(slV, v)
	}
	return slK, slV
}

实现简单,满足了我们对类型为 map[string]string 的转换。

但是面对其他类型的 map,比如 map[stirng]int,map[stirng]uint,map[stirng]bool…,按照上面的思路,每一个 map 类型都要实现一个转换函数,代码非常冗余。

实际上,可以借助 go reflect 反射能力和开源转换库 cast,写出一个支持泛型的转换函数。

// Map2SliceE converts keys and values of map to slice with error
func Map2SliceE(i interface{})([]interface{}, []interface{}, error) {
	kind := reflect.TypeOf(i).Kind()
	if kind != reflect.Map {
		return nil, nil, errors.New("the input is not a map")
	}
	m := reflect.ValueOf(i)
	keys := m.MapKeys()
	slK, slV := make([]interface{}, 0, len(keys)), make([]interface{}, 0, len(keys))
	for _, k := range keys {
		slK = append(slK, k.Interface())
		v := m.MapIndex(k)
		slV = append(slV, v.Interface())
	}
	return slK, slV, nil
}

// Map2StrSliceE converts keys and values of map to string slice with error
func Map2StrSliceE(i interface{})([]string, []string, error) {
	slK, slV, err := Map2SliceE(i)
	if err != nil {
		return nil, nil, err
	}
	k, err := cast.ToStringSliceE(slK)
	if err != nil {
		return nil, nil, err
	}
	v, err := cast.ToStringSliceE(slV)
	if err != nil {
		return nil, nil, err
	}
	return k, v, nil
}

转换示例:

package main

import (
	"errors"
	"fmt"
	"reflect"

	"github.com/spf13/cast"
)

func main() {
	m0 := map[string]string{"CN": "China", "HK": "Hong Kong", "AU": "Australia"}
	m1 := map[string]int{"CN":86, "HK":852,"AU":61}
	m2 := map[int]string{86:"China", 852:"Hong Kong",61:"Australia"}
	k0, v0, e0 := Map2StrSliceE(m0)
	k1, v1, e1 := Map2StrSliceE(m1)
	k2, v2, e2 := Map2StrSliceE(m2)
	fmt.Println(k0, v0, e0)
	fmt.Println(k1, v1, e1)
	fmt.Println(k2, v2, e2)
}

运行输出:

[CN HK AU] [China Hong Kong Australia] <nil>
[AU CN HK] [61 86 852] <nil>
[86 852 61] [China Hong Kong Australia] <nil>

注意:map 的遍历顺序是随机的,所以每次输出的结果可能不同。

为了方便调用,可以封一个不返回错误的版本。

// Map2StrSlice converts keys and values of map to string slice
func Map2StrSlice(i interface{})([]string, []string) {
	slK, slV, _ := Map2StrSliceE(i)
	return slK, slV
}

以上函数已开源至 GitHub 工具库 go-huge-util,可直接通过 go mod 方式 import 然后使用。

package main

import (
	"fmt"

	"github.com/dablelv/go-huge-util"
)

func main() {
	m := map[string]string{"CN": "China", "HK": "Hong Kong", "AU": "Australia"}
	fmt.Println(util.Map2StrSlice(m))
}

运行输出

[CN HK AU] [China Hong Kong Australia]

参考文献

[1] GitHub go-huge-util
[2] segmentfault.go语言,如何把map转为slice?

以上是关于Go map 转 slice的主要内容,如果未能解决你的问题,请参考以下文章

go map and slice 2021-10-08

[GO专栏-5]GO中5 分组声明与array, slice, map

转go里面字符串转成 字节slice, 字节slice转成字符串

Go 切片转集合(Slice to Set)

Go 切片转集合(Slice to Set)

Go 语言中的 Array,Slice,Map 和 Set