2012-11-16 10 views
47

Jeśli mam mapę m czy istnieje lepszy sposób na uzyskanie kawałek wartości v następnieCzy w golangu można uzyskać kawałek wartości z mapy?

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) 
} 

Czy istnieje wbudowaną funkcją mapie? Czy istnieje funkcja w pakiecie Go, czy jest to najlepszy kod, jeśli muszę?

+0

zamiast „_” w pętli for, nazywają to idx i rów IDX ++ działalność –

+0

Nie, nie mogę, gdy wahają się nad mapą powraca klucz, wartość nie indeksu wartości. W jego przykładzie używa on 1 jako pierwszego klucza, co spowoduje, że indeksy w wycinku v będą niepoprawne, ponieważ indeks początkowy będzie wynosił 1, a nie 4, a gdy osiągnie 4, będzie poza zakresem. https://play.golang.org/p/X8_SbgxK4VX – Popmedic

Odpowiedz

29

Niestety, nie. Nie ma wbudowanego sposobu, aby to zrobić.

Na marginesie, można pominąć argumentu zdolności w tworzeniu slice:

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

Pojemność zakłada się być taka sama jak długość tutaj.

28

Jako dodatek do jimt poście:

Można również wykorzystać append zamiast jawnie przypisaniu wartości do ich indeksów:

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) 
} 

Należy pamiętać, że długość jest (jeszcze żadne elementy obecne) zerowe, ale pojemność (przydzielone miejsce) jest inicjowana liczbą elementów z m. Dzieje się tak dlatego, że append nie musi przydzielać pamięci za każdym razem, gdy skończy się pojemność pliku v.

Możesz również wyciąć bez wartości pojemności i pozwolić append alokować pamięć dla siebie.

+0

Zastanawiam się, czy byłoby to wolniejsze (zakładając przypisanie z góry)? Zrobiłem prymitywny benchmark z mapą [int] int i wydawało mi się wolniejsze o 1-2%. Wszelkie pomysły, jeśli jest to coś, o co trzeba się martwić, czy po prostu z tym wyjść? – masebase

+1

Mogłabym założyć, że jest nieco wolniejsza, ale ta różnica jest w większości przypadków znikoma. [Benchmark porównujący bezpośrednie przypisanie i dołączenie] (http://pastie.org/5393131). – nemo

0

O ile obecnie wiem, idź nie ma sposobu metoda łączenia łańcuchów/bajtów w wynikowy ciąg bez podejmowania co najmniej/dwa/kopie.

Obecnie musisz wyhodować bajt [], ponieważ wszystkie wartości ciągów są const, THEN musisz użyć wbudowanego napisu, aby język utworzył "błogosławiony" obiekt typu string, który skopiuje bufor, ponieważ coś gdzieś może mieć odniesienie do adresu wspierającego bajt [].

Jeśli odpowiedni jest bajt [], możesz uzyskać bardzo niewielką przewagę nad bajtami. Funkcja JOIN, wykonując jedną alokację i wykonując kopię, wywołuje sam siebie.

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) 
} 
Powiązane problemy