Golang: convert slices into map
Asked Answered
C

6

37

Is there an easy/simple means of converting a slice into a map in Golang? Like converting an array into hash in perl is easy to do with simple assignment like %hash = @array this above will convert all the elements in the array into a hash, with keys being even-numbered index elements while the values will be odd-numbered index elements of the array.

In my Go code, I have slices of string and would like to convert it into a map. I am wondering if there is a Go's library code to do this.

func main() {
  var elements []string
  var elementMap map[string]string
  elements = []string{"abc", "def", "fgi", "adi"}
}

elements slice should be converted into map of strings, elementMap.

thanks

Conte answered 26/7, 2016 at 0:46 Comment(0)
I
36

Use a for loop:

elements = []string{"abc", "def", "fgi", "adi"}
elementMap := make(map[string]string)
for i := 0; i < len(elements); i +=2 {
    elementMap[elements[i]] = elements[i+1]
}

runnable example on the playground

The standard library does not have a function to do this.

Inelegance answered 26/7, 2016 at 0:48 Comment(0)
L
9

There is currently no way to do it the perl way. You just have to iterate the slice, and place the slice elements in your map, e.g. as the map's key:

func main() {
    var elements []string
    var elementMap map[string]string
    elements = []string{"abc", "def", "fgi", "adi"}

    // initialize map
    elementMap = make(map[string]string)

    // put slice values into map
    for _, s := range elements {  
        elementMap[s] = s
        // or just keys, without values: elementMap[s] = ""
    }

    // print map
    for k := range elementMap {
        fmt.Println(k)
    }
}

Depending on what you want to do, you have to keep one thing in mind: map keys are unique, so if your slice contains duplicate strings you might want to keep count by using a map[string]int:

func main() {
    var elements []string
    var elementMap map[string]int
    elements = []string{"abc", "def", "fgi", "adi", "fgi", "adi"}

    // initialize map
    elementMap = make(map[string]int)

    // increment map's value for every key from slice
    for _, s := range elements {  
        elementMap[s]++
    }

    // print map
    for k, v := range elementMap {
        fmt.Println(k, v)
    }
}

And you can always wrap that functionality in a func:

func sliceToStrMap(elements []string) map[string]string {
    elementMap := make(map[string]string)
    for _, s := range elements {
        elementMap[s] = s
    }
    return elementMap
}

func sliceToIntMap(elements []string) map[string]int {
    elementMap := make(map[string]int)
    for _, s := range elements {
        elementMap[s]++
    }
    return elementMap
}
Leprose answered 19/6, 2017 at 11:16 Comment(0)
E
6

With generics:

func Map[T any, V comparable](src []T, key func(T) V) map[V]T {
    var result = make(map[V]T)
    for _, v := range src {
        result[key(v)] = v
    }
    return result
}
Euphemia answered 1/7, 2022 at 6:54 Comment(1)
This is a useful answer, but it’s more idiomatic to use K for the key type and V or T for the value typeMagyar
A
3

If looking for a library you can use go-funk. This code may be less performant and not idiomatic in Go until we have Generics.

var elements = []string{"abc", "def", "fgi", "adi"}

elementsMap := funk.Map(
    funk.Chunk(elements, 2),
    func(x []string) (string, string) { // Slice to Map
        return x[0], x[1]
    },
)

fmt.Println(elementsMap) // map[abc:def fgi:adi]

https://play.golang.org/p/-t-33z4aKM_j

Authoritarian answered 7/11, 2019 at 12:23 Comment(0)
R
2

Try with range

elements := []string{"abc", "def", "fgi", "adi"}
    elementMap := make(map[int]string)
    for i, data := range elements  {
             elementMap[i] = data
        }

fmt.Println(elementMap ) // map[0:abc 1:def 2:fgi 3:adi]

https://play.golang.org/p/h6uZn5obLKg

Refined answered 10/8, 2020 at 8:6 Comment(0)
G
0

this is same soluation like some sliding windows question answer a much result slice have more than one map keys:

    
func zipSlices[T any, V comparable](src []T, size int, keyf func(idx int) V) []map[V]T {

    var results = []map[V]T{}
    total := len(src)
    if total < size {
        return results 
    }
    for idx := 0; idx <= total; idx += size {
        var j int
        var newOne = make(map[V]T)
        for {
            if j >= size {
                j = 0  
                break
            } 

            if idx+j >= total {
                break
            }
            newOne[keyf(j)] = src[idx+j]
            j += 1
        }

        if len(result) > 0 {
            results = append(results , newOne)
        }
    }
    return results 
}
Gianina answered 20/10, 2022 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.