Wednesday, November 28, 2018

Go By Examples - Map types Advanced Programs

This post covers  Golang Map types tutorials with examples 

In my previous post, Covered Map guide in Golang

Following are the  Map type  examples in Go Language

Sort a Map by key or values

The map is ordered data structure of key-value pairs. To sort map, We have to write a custom to handle this, For example, we have a map of string key and int values. Printing the map returns map data in random order, the order is not guaranteed.
func main() {
 employees := map[string]int{"Kiran": 2030, "John": 10210, "Mark": 25000}
 fmt.Println(employees)
 fmt.Println(employees)
 fmt.Println(employees)
 fmt.Println(employees)
 fmt.Println(employees)
}
Output is
map[John:10210 Mark:25000 Kiran:2030]
map[John:10210 Mark:25000 Kiran:2030]
map[Kiran:2030 John:10210 Mark:25000]
map[Mark:25000 Kiran:2030 John:10210]
map[Kiran:2030 John:10210 Mark:25000]
We will see the map sort based on key order
package main

import (
 "fmt"
 "sort"
)

func main() {
 employees := map[string]int{"Kiran": 2030, "John": 10210, "Mark": 25000}
 fmt.Println(employees)

 keys := make([]string, 0, len(employees))
 for k := range employees {
  keys = append(keys, k)
 }
 sort.Strings(keys)
 for _, k := range keys {
  fmt.Println(k, employees[k])
 }
}
The map is displayed with key ordered and Output is
map[Mark:25000 Kiran:2030 John:10210]
John 10210
Kiran 2030
Mark 25000

Create a Nested Map type with an array of maps 

 In this example, you can create a Map with key as strings and value as Array of Maps First Create a Map with an array of maps using make a function of literal syntax
 mapArraysMap := map[string][]map[string]string{
  "kiran": {{"id": "1"}, {"name": "kiran"}},
  "john":  {{"id": "2"}, {"name": "kiran"}},
 }
This creates a Map with the key is string assigned with a value of an array of maps Adding and deleting element work the same way like a normal maps Complete example of Map with an array of maps
package main

import (
 "fmt"
)

func main() {

 //Create a Map with array of map
 mapArraysMap := map[string][]map[string]string{
  "kiran": {{"id": "1"}, {"name": "kiran"}},
  "john":  {{"id": "2"}, {"name": "kiran"}},
 }
 fmt.Println(mapArraysMap)
 fmt.Println("Original length: ", len(mapArraysMap))
 //Adding an Array of Map values to map
 mapArraysMap["frank"] = []map[string]string{{"id": "2"}, {"name": "kiran"}}
 fmt.Println(mapArraysMap)
 fmt.Println("length: ", len(mapArraysMap))
 //Delete entry from Map
 delete(mapArraysMap, "frank")
 fmt.Println("length: ", len(mapArraysMap))

}
Output is
map[3:Gef 1:ram 2:arun]
map[kiran:[map[id:1] map[name:kiran]] john:[map[id:2] map[name:kiran]]]
Original length:  2
map[john:[map[id:2] map[name:kiran]] frank:[map[id:2] map[name:kiran]] kiran:[map[id:1] map[name:kiran]]]
length:  3
length:  2

Convert Slice/Array to from Map 

 Slice is a dynamic array and its length grows at runtime. The map is a collection with key and value pairs. The map is good in performance for search, add and delete, but not good for Iteration There are no standard API functions to convert String to Map Sometimes we need to convert Slice string Declared and initialize a slice with string literals like below
//create a slice with string literal
countries := []string{"india", "USA", "UK", "France"}
And also create a Map with the key is integer and value is string Iterate slice either simple for loop or for loop with range Here is a complete example
package main

import (
 "fmt"
)

func main() {

 //create a slice with string literal
 countries := []string{"india", "USA", "UK", "France"}
 fmt.Println(countries)
 // Create and initilize a Map with make function
 countriesMap := make(map[int]string)
 // Iterate Slice
 for i := 0; i < len(countries); i++ {
  countriesMap[i] = countries[i]
 }
 fmt.Println(countriesMap)
}
Output is
[india USA UK France]
map[2:UK 3:France 0:india 1:USA]
Since Map is an unordered data structure, When you run the above program multiple times, the order of displayed data might changes.

Convert Map to Key/value/ item Slice of arrays 

Often we need to retrieve keys, values or both from a Map type.
For example, We have a Map with the key and values of string types.
The Below program talks about below things

  • Slice of keys from Map 
  • An array of values from Map 
  • Key-value of item slices from Map 

Here is an example for Convert Map to Key/values/items Slices
package main

import (
 "fmt"
)

func main() {
 // Create and intilize map with string literals - First Name - Last Name
 names := map[string]string{
  "kiran":  "Babu",
  "John":   "Frank",
  "Silver": "Stallin",
 }
 fmt.Println("Map   ", names)
 fmt.Println("Key value ", names)

 // Retrieve keys of slice from Map
 keys := []string{}
 for key, _ := range names {
  keys = append(keys, key)
 }
 fmt.Println("Keys  ", keys)

 // Retrieve values of slice from Map
 values := []string{}
 for _, value := range names {
  values = append(values, value)
 }
 fmt.Println("Values ", values)

 // Retrieve  slice of key-value pairs from Map
 items := [][]string{}
 for key, value := range names {
  items = append(items, []string{key, value})
 }
 fmt.Println("Values ", items)

}
Output is
Map    map[kiran:Babu John:Frank Silver:Stallin]
Key value  map[Silver:Stallin kiran:Babu John:Frank]
Keys   [Silver kiran John]
Values  [Frank Stallin Babu]
Values  [[Silver Stallin] [kiran Babu] [John Frank]]

Merge Two or more maps into single Map 

There is no standard function to merge or join the maps. We have to write a custom to merge multiple maps into a single map. Result Map might have multiple values for given key, so the value should be declared as slice and then the output map of type map[string][]string
Here is the map merge process
  • Iterate the maps 
  • For each iteration, Append each value from source map to slice for the given key of output map 
  • once slice map is appended, we have to assign this slice to output map for given key 
  • This process allows duplicates elements in the output map 

here is complete example map merge
package main

import (
 "fmt"
)

func main() {
 m1 := map[string]string{"k1": "v1"}
 m2 := map[string]string{"k2": "v2"}
 m3 := map[string]string{"k1": "v3"}

 output := mergeMaps(m1, m2, m3)
 fmt.Println(output)

}
func mergeMaps(maps ...map[string]string) map[string][]string {
 result := map[string][]string{}
 for _, m := range maps {
  for k, v := range m {
   result[k] = append(result[k], v)
  }
 }
 return res
}
The output of the above program
map[id_1:[val_1 val_3] id_2:[val_2]]

How to Check Type of Key and values of Map - Reflection API 

We can get the type of map, keys, and values using Standard Reflection API reflect.TypeOf() function returns the dynamic type of given variable it returns nil if given variable is nil interface
reflect.TypeOf().key() function returns the map key data type It throws a panic error if given type is not map type
reflect.TypeOf().elem() function returns the map value data type It throws panic error if given type is not map Herea is complete example
package main

import (
 "fmt"
 "reflect"
)

func main() {

 var mymap map[string]int
 fmt.Println("Map Type: ", reflect.TypeOf(mymap))
 fmt.Println("Map Key Type: ", reflect.TypeOf(mymap).Key())
 fmt.Println("Map Value Type: ", reflect.TypeOf(mymap).Elem())

 mapArraysMap := map[string][]map[string]string{
  "kiran": {{"id": "1"}, {"name": "kiran"}},
 }
 fmt.Println("Map Type: ", reflect.TypeOf(mapArraysMap))
 fmt.Println("Map Key Type: ", reflect.TypeOf(mapArraysMap).Key())
 fmt.Println("Map Value Type: ", reflect.TypeOf(mapArraysMap).Elem())

}
Output is
Map Type:  map[string]int
Map Key Type:  string
Map Value Type:  int
Map Type:  map[string][]map[string]string
Map Key Type:  string
Map Value Type:  []map[string]string

Convert Struct type with Map into JSOn type 

We have declared a struct with each element of the standard object of strings except Address element. Address element is of a map of strings
type Employee struct {
 Id      string            `json:"id,omitempty"`
 Name    string            `json:"name,omitempty"`
 Address map[string]string `json:"address,omitempty"`
}
Will conver this struct to JSOn using json.MarshalIndent() function Following is an example
package main

import (
 "encoding/json"
 "fmt"
)

// Declare Struct type
type Employee struct {
 Id      string            `json:"id,omitempty"`
 Name    string            `json:"name,omitempty"`
 Address map[string]string `json:"address,omitempty"`
}

func main() {
 // Initialized Struct and add data to it
 var emp Employee
 emp.Id = "1"
 emp.Name = "Frank"
 m := make(map[string]string)
 emp.Address = m
 emp.Address["city"] = "Newyork"
 emp.Address["country"] = "USA"
 emp.Address["zipcode"] = "92451"

 var data []byte
 // Convert struct to json
 data, _ = json.MarshalIndent(emp, "", "    ")

 fmt.Println(string(data))
}
Output is
{
    "id": "1",
    "name": "Frank",
    "address": {
        "Country": "USA",
        "city": "Newyork",
        "zipcode": "92451"
    }
}

Related article


EmoticonEmoticon