[go] golang에서 맵에서 값 조각을 얻는 좋은 방법이 있습니까?

내가 맵을 가지고 있다면 m 값의 조각을 얻는 더 좋은 방법이 있습니까?

package main
import (
  "fmt"
)

func main() {
    m := make(map[int]string)

    m[1] = "a"
    m[2] = "b"
    m[3] = "c"
    m[4] = "d"

    // Can this be done better?
    v := make([]string, len(m), len(m))
    idx := 0
    for  _, value := range m {
       v[idx] = value
       idx++
    }

    fmt.Println(v)
 }

지도에 내장 된 기능이 있습니까? Go 패키지에 함수가 있습니까, 아니면 이것이 내가 필요한 경우 수행 할 수있는 가장 좋은 코드입니까?



답변

불행하게도. 이를 수행하는 기본 제공 방법은 없습니다.

참고로, 슬라이스 생성에서 용량 인수를 생략 할 수 있습니다.

v := make([]string, len(m))

용량은 여기의 길이와 동일 함을 의미합니다.


답변

jimt의 게시물에 추가로 :

append인덱스에 값을 명시 적으로 할당하는 대신 사용할 수도 있습니다 .

m := make(map[int]string)

m[1] = "a"
m[2] = "b"
m[3] = "c"
m[4] = "d"

v := make([]string, 0, len(m))

for  _, value := range m {
   v = append(v, value)
}

길이는 0 (아직 요소가 없음)이지만 용량 (할당 된 공간)은의 요소 수로 초기화됩니다 m. 이렇게 append하면 슬라이스 용량이 부족할 때마다 메모리를 할당 할 필요가 없습니다 v.

make용량 값이없는 슬라이스 도 append자체 메모리를 할당 할 수 있습니다.


답변

내가 현재 아는 한, go에는 최소한 / two / 복사본을 만들지 않고 문자열 / 바이트를 결과 문자열에 연결하는 방법이 없습니다.

모든 문자열 값이 const이므로 현재 [] 바이트를 늘려야합니다. 그런 다음 언어가 ‘축복 된’문자열 객체를 생성하도록 문자열 내장을 사용해야합니다. 어딘가에 참조가있을 수 있으므로 버퍼를 복사합니다. [] 바이트를 뒷받침하는 주소로.

[] 바이트가 적합하면 하나의 할당을 만들고 복사를 수행하여 자신을 호출함으로써 bytes.Join 함수에 대해 약간의 리드를 얻을 수 있습니다.

package main
import (
  "fmt"
)

func main() {
m := make(map[int]string)

m[1] = "a" ;    m[2] = "b" ;     m[3] = "c" ;    m[4] = "d"

ip := 0

/* If the elements of m are not all of fixed length you must use a method like this;
 * in that case also consider:
 * bytes.Join() and/or
 * strings.Join()
 * They are likely preferable for maintainability over small performance change.

for _, v := range m {
    ip += len(v)
}
*/

ip = len(m) * 1 // length of elements in m
r := make([]byte, ip, ip)
ip = 0
for  _, v := range m {
   ip += copy(r[ip:], v)
}

// r (return value) is currently a []byte, it mostly differs from 'string'
// in that it can be grown and has a different default fmt method.

fmt.Printf("%s\n", r)
}


답변

maps패키지 를 사용할 수 있습니다 .

go get https://github.com/drgrib/maps

그럼 당신이 전화해야 할 것은

values := maps.GetValuesIntString(m)

일반적인 map조합에 대해 형식이 안전합니다 . 동일한 패키지에서 도구 generatemap사용하는 다른 유형에 대해 다른 유형 안전 함수를 사용할 수 있습니다 mapper.

전체 공개 : 나는이 패키지의 작성자입니다. 이 기능을 map반복적으로 다시 작성했기 때문에 만들었습니다 .


답변

반드시 더 좋은 것은 아니지만이를 수행하는 더 깨끗한 방법은 슬라이스 길이와 용량을 다음 과 같이 정의하는 것입니다.txs := make([]Tx, 0, len(txMap))

    // Defines the Slice capacity to match the Map elements count
    txs := make([]Tx, 0, len(txMap))

    for _, tx := range txMap {
        txs = append(txs, tx)
    }

전체 예 :

package main

import (
    "github.com/davecgh/go-spew/spew"
)

type Tx struct {
    from  string
    to    string
    value uint64
}

func main() {
    // Extra touch pre-defining the Map length to avoid reallocation
    txMap := make(map[string]Tx, 3)
    txMap["tx1"] = Tx{"andrej", "babayaga", 10}
    txMap["tx2"] = Tx{"andrej", "babayaga", 20}
    txMap["tx3"] = Tx{"andrej", "babayaga", 30}

    txSlice := getTXsAsSlice(txMap)
    spew.Dump(txSlice)
}

func getTXsAsSlice(txMap map[string]Tx) []Tx {
    // Defines the Slice capacity to match the Map elements count
    txs := make([]Tx, 0, len(txMap))
    for _, tx := range txMap {
        txs = append(txs, tx)
    }

    return txs
}

간단한 솔루션이지만 많은 문제가 있습니다. 자세한 내용은이 블로그 게시물을 참조하세요. https://web3.coach/golang-how-to-convert-map-to-slice-three-gotchas


답변