2012-11-16 7 views
47

Wenn ich eine Karte m haben, ist es eine bessere Art und Weise eine Scheibe der Werte des Erhaltens v dannIn Golang gibt es eine nette Möglichkeit, ein Stück Werte von einer Karte zu bekommen?

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

Gibt es eine eingebaute Funktion einer Karte? Gibt es eine Funktion in einem Go-Paket oder ist dies der beste Code, den ich tun muss, wenn ich muss?

+0

statt ‚_‘ in Ihrer for-Schleife, nennen es idx und Graben der idx ++ Geschäft –

+0

Nein, kann er nicht, wenn Sie eine Karte, um diese Schlüssel zurückgibt -umspannen, Wert nicht Index, Wert. In seinem Beispiel verwendet er 1 als ersten Schlüssel und das wird die Indizes in der Scheibe v inkorrekt machen, weil der Startindex 1 nicht Null ist, und wenn er auf 4 kommt, wird er außerhalb des Bereichs liegen. https://play.golang.org/p/X8_SbgxK4VX – Popmedic

Antwort

29

Leider nein. Es gibt keinen eingebauten Weg, dies zu tun.

Als Randbemerkung, können Sie die Kapazität Argument in Ihrer Scheibe Schöpfung wegzulassen:

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

Die Kapazität die gleiche wie die Länge, hier zu sein impliziert.

28

Als Ergänzung zu jimt der Beitrag:

Sie auch append nicht explizit die Werte auf ihre Indizes Zuweisung verwenden:

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

Beachten Sie, dass die Länge Null (keine Elemente vorhanden noch), aber Die Kapazität (zugewiesener Speicherplatz) wird mit der Anzahl der Elemente von m initialisiert. Dies geschieht so, dass append Speicher nicht jedes Mal reservieren muss, wenn die Kapazität des Slice v abläuft.

Sie könnten auch make die Scheibe ohne den Kapazitätswert und lassen append den Speicher für sich reservieren.

+0

Ich fragte mich, ob dies etwas langsamer wäre (Annahme von vorne Zuteilung)? Ich habe einen groben Benchmark mit einer Karte [int] int gemacht und es schien ungefähr 1-2% langsamer zu sein. Irgendwelche Ideen, wenn das etwas ist, worüber man sich Sorgen machen oder einfach damit gehen muss? – masebase

+1

Ich würde annehmen, append ein bisschen langsamer zu sein, aber dieser Unterschied ist in den meisten Fällen vernachlässigbar. [Vergleich Benchmark direkte Zuordnung und append] (http://pastie.org/5393131). – nemo

0

Soweit mir bekannt ist, hat go keine Methode zum Verketten von Strings/Bytes in einer resultierenden Zeichenkette, ohne mindestens zwei Kopien zu machen.

Sie müssen derzeit ein [] Byte vergrößern, da alle Zeichenfolgenwerte const sind. DANN müssen Sie die eingebaute Zeichenfolge verwenden, damit die Sprache ein "gesegnetes" Zeichenfolgenobjekt erstellt, in das der Puffer seit etwas kopiert wird könnte einen Verweis auf die Adresse hinter dem [] Byte haben.

Wenn ein [] Byte geeignet ist, dann können Sie einen sehr leichten Vorsprung gegenüber der bytes.Join Funktion erlangen, indem Sie eine Zuweisung machen und die Kopie selbst aufrufen.

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