Если у меня есть карта m, есть ли лучший способ получить фрагмент значений v, тогда
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, или это лучший код, который мне нужно сделать?
_
наidx
и используйтеidx-1
при присвоении значений срезов.Ответы:
К сожалению нет. Для этого нет встроенного способа.
В качестве примечания, вы можете опустить аргумент емкости при создании среза:
v := make([]string, len(m))
Подразумевается, что емкость должна быть такой же, как и длина.
источник
В дополнение к сообщению Джимта:
Вы также можете использовать
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) }
Обратите внимание, что длина равна нулю (элементов еще нет), но емкость (выделенное пространство) инициализируется количеством элементов
m
. Это сделано, поэтомуappend
не нужно выделять память каждый раз, когдаv
заканчивается емкость среза .Вы также можете
make
вырезать срез без значения емкости и позволитьappend
выделить память для себя.источник
make([]appsv1.Deployment, len(d))
будет добавлено к группе пустых элементов, которые были созданы, когда вы выделилиlen(d)
пустые элементы.Насколько мне известно, в go нет способа конкатенации строк / байтов в результирующую строку без создания как минимум / двух / копий.
В настоящее время вам необходимо увеличить байт [], так как все строковые значения являются константными, ЗАТЕМ вы должны использовать встроенную строку, чтобы язык создал «благословенный» строковый объект, для которого он скопирует буфер, поскольку где-то может быть ссылка на адрес, поддерживающий байт [].
Если подходит байт [], то вы можете получить очень небольшое преимущество по сравнению с функцией 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
Тогда все, что вам нужно позвонить, это
Это типобезопасный для этой общей
map
комбинации. Вы можете использоватьgenerate
другие типобезопасные функции для любого другого типаmap
использования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
источник