2014-01-26 10 views
110

Gibt es eine einfachere/bessere Möglichkeit, ein Stück Schlüssel von einer Karte in Go zu bekommen?Golang - Ein Stück Schlüssel von einer Karte erhalten

Aktuell über die Karte Ich bin Iterieren und das Kopieren der Schlüssel zu einer Scheibe:

i := 0 
keys := make([]int, len(mymap)) 
for k := range mymap { 
    keys[i] = k 
    i++ 
} 

Antwort

116

Zum Beispiel

package main 

func main() { 
    mymap := make(map[int]string) 
    keys := make([]int, 0, len(mymap)) 
    for k := range mymap { 
     keys = append(keys, k) 
    } 
} 

hineingehen effizient zu sein, ist es wichtig, Speicherzuordnungen zu minimieren.

+12

Es ist ein bisschen besser, die tatsächliche Größe anstelle der Kapazität einzustellen und Anhängen insgesamt zu vermeiden. Siehe meine Antwort für Details. –

+1

Beachten Sie, dass, wenn 'mymap' keine lokale Variable ist (und daher wächst/schrumpft), dies die einzig richtige Lösung ist - es stellt sicher, dass, wenn die Größe von 'mymap' sich zwischen der Initialisierung von 'keys' und "for" -Schleife, es wird keine Out-of-Bounds-Probleme geben. – Melllvar

+3

Karten sind unter gleichzeitigem Zugriff nicht sicher, keine der beiden Lösungen ist akzeptabel, wenn eine andere Goroutine die Karte ändern könnte. –

6

Ein schöner Weg, dies zu tun wäre append zu verwenden:

keys = []int{} 
for k := range mymap { 
    keys = append(keys, k) 
} 

Other than that, Sie 'Pech gehabt - Go ist keine sehr ausdrucksstarke Sprache.

+0

Das sieht besser :-) –

+8

Es ist weniger effizient als das Original, obwohl - hängen führt mehrere Zuordnungen durch, um das zugrunde liegende Array zu vergrößern, und muss die Schichtlänge bei jedem Aufruf aktualisieren. Wenn man 'keys = make ([] int, 0, len (mymap))' sagt, werden die Zuweisungen gelöscht, aber ich erwarte, dass es immer noch langsamer wird. –

195

Das ist eine alte Frage, aber hier sind meine zwei Cent. PeterSOs Antwort ist etwas prägnanter, aber etwas weniger effizient. Sie wissen bereits, wie groß es sein wird, so dass Sie nicht einmal brauchen append zu verwenden:

keys := make([]int, len(mymap)) 

i := 0 
for k := range mymap { 
    keys[i] = k 
    i++ 
} 

In den meisten Fällen wird es wahrscheinlich nicht viel Unterschied machen, aber es ist nicht viel mehr Arbeit, und in Meine Tests (mit einer Karte mit 1.000.000 zufälligen Schlüsseln int64 und dann das Array der Schlüssel zehn Mal mit jeder Methode zu generieren), war es etwa 20% schneller, Mitglieder des Arrays direkt zuzuweisen als append zu verwenden.

Obwohl das Festlegen der Kapazität Neuzuweisungen eliminiert, muss Append noch zusätzliche Arbeit zu tun, um zu überprüfen, ob Sie die Kapazität bei jedem Anhängen erreicht haben.

+4

Ich denke, das sollte die akzeptierte Antwort sein. – djhworld

+24

Dies sieht genauso aus wie der OP-Code. Ich stimme zu, dass dies der bessere Weg ist, aber ich bin neugierig, ob ich den Unterschied zwischen dem Code dieser Antwort und dem Code von OP verpasst habe. –

+1

Guter Punkt, sah ich irgendwie die anderen Antworten und verpasste, dass meine Antwort genau das gleiche wie das OP ist. Na ja, zumindest wissen wir jetzt ungefähr, was die Strafe für die Verwendung von Append unnötig ist :) –

39

Sie auch eine Reihe von Tasten mit Art []Value durch Verfahren MapKeys von struct Value aus dem Paket nehmen „spiegeln“:

package main 

import (
    "fmt" 
    "reflect" 
) 

func main() { 
    abc := map[string]int{ 
     "a": 1, 
     "b": 2, 
     "c": 3, 
    } 

    keys := reflect.ValueOf(abc).MapKeys() 

    fmt.Println(keys) // [a b c] 
} 
Verwandte Themen