본문 바로가기
IT 초보코딩의 세계/Go 언어

Go언어의 자료구조 맵(Map)와 컨테이너

by 조이럭키7 2023. 3. 30.
반응형

지난 포스팅에서는 배열과 슬라이스에 대해서 알아보았으며 숙지하지 않았다면 아래 포스팅을 참조하자

https://joylucky7.tistory.com/26

 

Go언어의 자료구조 배열과 슬라이스 1장

◆ 배열 ● 동일한 자료형 겂들의 집합 ● 크기가 고정 ● 선언과 초기화 package main import ( "fmt" ) func main() { var ar1 [3]int ar1 = [3]int{1, 2, 3} fmt.Println(ar1) var ar2 = [3]int{10, 20, 3} fmt.Println(ar2) } ● 데이터

joylucky7.tistory.com


맵(Map)

맵은 해시 테이블 또는 딕셔너리라고도 하며 키-값 형태로 자료를 저장

 슬라이스와 마찬가지로 레퍼런스 타입

◆ 생성방법으로는 

var 맵이름 map[키_자료형]값_자료형
var a map[string]int // 키는 string, 값은 int인 맵 선언

      ▶ [ ] (대괄호) 안에는 키의 자료형을 지정하고 그 뒤에 값의 자료형을 지정

◆ 초기화

{key:value, key:value …}

◆ 데이터 접근

맵이름[키이름]

      ▶ 없는 키의 경우는 기본값

      ▶ 실제 리턴되는 데이터는 2개인데 첫번째 데이터는 값이고 두번째 데이터는 값의 존재 여부

      ▶ 데이터를 접근할 때 값을 대입하면 데이터가 추가되거나 수정됨

맵은 make 함수를 사용하여 공간을 할당할 수 있는데 맵 선언과 동시에 make 함수를 사용하면 map 키워드와 자료형을 생략할 수 있음

:= 사용하여 var 생략할 수 있음

make(map[키_자료형]값_자료형)

생성 과 동시에 초기화

package main

import (
  "fmt"
)
func main() {
  a := map[string]string{"name": "joylucky", "age": "34"}
  fmt.Println(a["name"])
  _, ok := a["name"]
  fmt.Println(ok)

  fmt.Println(a["address"])
  _, ok = a["address"]
  fmt.Println(ok)
}

맵 순회

      ▶ for ,:= range(맵이름){}

package main

import (
  "fmt"
)
func main() {
  a := map[string]string{"name": "joylucky", "age": "34"}
  for key, value := range(a){
  fmt.Printf("%s:%s\n", key, value)
  }
}

 맵 데이터 삭제

      ▶ delete(, 삭제할 키)

package main

import (
  "fmt"
)
func main() {
  a := map[string]string{"name": "joylucky", "age": "34"}
  delete(a, "age")
  for key, value := range(a){
  fmt.Printf("%s:%s\n", key, value)
  }
}

 맵 안에 데이터로 맵 사용 가능

package main

import "fmt"

func main() {

  terrestrialPlanet := map[string]map[string]float32{
           "Mercury": map[string]float32{
                  "meanRadius":    2439.7,
                  "mass":          3.3022E+23,
                  "orbitalPeriod": 87.969,
  },
             "Venus": map[string]float32{
                    "meanRadius":    6051.8,
                    "mass":          4.8676E+24,
                    "orbitalPeriod": 224.70069,
  },
             "Earth": map[string]float32{
                    "meanRadius":    6371.0,
                    "mass":          5.97219E+24,
                    "orbitalPeriod": 365.25641,
  },
             "Mars": map[string]float32{
                    "meanRadius":    3389.5,
                    "mass":          6.4185E+23,
                    "orbitalPeriod": 686.9600,
  },
  }
  for key, value := range(terrestrialPlanet){
                    fmt.Printf("%s\n", key)
                    for subKey, subValue := range(value){
                          fmt.Printf("%s:%f", subKey, subValue)
                    }
                     fmt.Println()
  }
}

◆ 맵의 배열

package main

import "fmt"

func main() {
  haitai := []string{"이대진", "최향남", "이종범", "선동열", "김상진"}
  kia := []string{"윤석민", "양현종", "이범호", "김주찬"}
  kbo := map[string][]string{
          "haital": haitai,
          "kia": kia,
  }
  for key, value := range(kbo){
          fmt.Printf("%s\n", key)
          for _, player := range(value){
                  fmt.Printf("%s\t", player)
          }
          fmt.Println()
  }
}

컨테이너(Container)

container/list 패키지에서 제공하는 함수

package main

import (
  "container/list"
  "fmt"
)

func main() {
  l := list.New() // 연결 리스트 생성
  l.PushBack("디아블로")  // 연결 리스트에 데이터 추가
  l.PushBack("조이럭키")
  l.PushBack("워크래프")
  l.PushBack("스타크래프트")

  fmt.Println("Front ", l.Front().Value) // 연결 리스트의 맨 앞 데이터를 가져옴
  fmt.Println("Back ", l.Back().Value)   // 연결 리스트의 맨 뒤 데이터를 가져옴

  for e := l.Front(); e != nil; e = e.Next() { // 연결 리스트의 맨 앞부터 끝까지 순회
  fmt.Println(e.Value)
  }
}

container/heap 패키지에서 제공하는 함수

      ▶ func lnit(h Interface): 초기화

      ▶ func Push(h Interface, x interface!}): 힙에 데이터 추가

package main

import (
  "container/heap"
  "fmt"
)

type MinHeap []int // 힙을 int 슬라이스로 정의

func (h MinHeap) Len() int {
  return len(h) // 슬라이스의 길이를 구함
}

func (h MinHeap) Less(i, j int) bool {
  r := h[i] < h[j] // 대소관계 판단
  fmt.Printf("Less %d < %d %t\n", h[i], h[j], r)
  return r
}

func (h MinHeap) Swap(i, j int) {
  fmt.Printf("Swap %d %d\n", h[i], h[j])
  h[i], h[j] = h[j], h[i] // 값의 위치를 바꿈
}

func (h *MinHeap) Push(x interface{}) {
  fmt.Println("Push", x)
  *h = append(*h, x.(int)) // 맨 마지막에 값 추가
}

func (h *MinHeap) Pop() interface{} {
  old := *h
  n := len(old)
  x := old[n-1]     // 슬라이스의 맨 마지막 값을 가져옴
  *h = old[0 : n-1] // 맨 마지막 값을 제외한 슬라이스를 다시 저장
  return x
}

func main() {
  data := new(MinHeap) // 힙 생성

  heap.Init(data)    // 힙 초기화
  heap.Push(data, 5) // 힙에 데이터 추가
  heap.Push(data, 2)
  heap.Push(data, 7)
  heap.Push(data, 3)

  fmt.Println(data, "최솟값 : ", (*data)[0])
}

      ▶ func New(n int) *Ring: 링 생성

      ▶ func (r *Ring) Do(f func(interface{})): 링의 모든 노드 순회

      ▶ func (r *Ring) Move(n int) *Ring: 링을 회전시킴. 매개변수로 양수를 넣으면 시계 방향, 음수를 넣으면 반 시계 방향으로 회전

package main

import (
  "container/ring"
  "fmt"
)

func main() {
  data := []string{"Maria", "John", "Andrew", "James"}

  r := ring.New(len(data))       // 노드의 개수를 지정하여 링 생성
  for i := 0; i < r.Len(); i++ { // 링 노드 개수만큼 반복
  r.Value = data[i]      // 링의 노드에 값 넣기
  r = r.Next()           // 다음 노드로  이동
  }

  r.Do(func(x interface{}) { // 링의 모든 노드 순회
  fmt.Println(x)
  })

  fmt.Println("Move forward :")
  r = r.Move(1) // 링을 시계 방향으로 1노드 만큼 회전

  fmt.Println("Curr : ", r.Value)        // Curr :  John
  fmt.Println("Prev : ", r.Prev().Value) // Prev :  Maria
  fmt.Println("Next : ", r.Next().Value) // Next :  Andrew
}
반응형

댓글