Go'daki bir haritadan bir dilim anahtar almanın daha basit / daha güzel bir yolu var mı?
Şu anda harita üzerinde yineleme ve bir dilim anahtarları kopyalama:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
Go'daki bir haritadan bir dilim anahtar almanın daha basit / daha güzel bir yolu var mı?
Şu anda harita üzerinde yineleme ve bir dilim anahtarları kopyalama:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
Yanıtlar:
Örneğin,
package main
func main() {
mymap := make(map[int]string)
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
}
Go'da verimli olmak için bellek ayırmalarını en aza indirmek önemlidir.
mymapYerel bir değişken değilse (ve bu nedenle büyümeye / daralmaya maruz kalıyorsa ), bunun tek uygun çözüm olduğunu unutmayın - mymapbaşlatma keysve fordöngü arasındaki değişikliklerin boyutunun herhangi bir çıkış olmayacağını garanti eder. sınırları aşan sorunlar.
Bu eski bir soru, ama işte benim iki sentim. PeterSO'nun cevabı biraz daha özlü, ancak biraz daha az verimli. Ne kadar büyük olacağını zaten biliyorsunuz, bu yüzden append kullanmanıza bile gerek yok:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
Çoğu durumda, muhtemelen çok fazla bir fark yaratmaz, ancak daha fazla iş değildir ve testlerimde (1.000.000 rastgele bir harita kullanarak) int64 anahtar ve daha sonra her yöntemle on kez anahtar dizisi oluşturmak), Dizinin üyelerini atamaktan doğrudan atamaktan% 20 daha hızlı.
Kapasitenin ayarlanması yeniden tahsisleri ortadan kaldırsa da, append'in her bir append'in kapasitesine ulaşıp ulaşmadığınızı kontrol etmek için ekstra iş yapması gerekir.
for i, k := range mymap{? Bu şekilde i ++ 'a ihtiyacınız yok mu?
i, k := range mymap, o izaman anahtar kolacak ve haritadaki bu anahtarlara karşılık gelen değerler olacaktır. Bu aslında bir dilim anahtarı doldurmanıza yardımcı olmaz.
Ayrıca "reflektör" paketindeki yapı []Valueyöntemine MapKeysgöre türe sahip bir anahtar dizisi de alabilirsiniz Value:
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]
}
[]string?
Bunu yapmanın daha güzel bir yolu append:
keys = []int{}
for k := range mymap {
keys = append(keys, k)
}
Bunun dışında şansınız kalmadı - Go çok etkileyici bir dil değil.
keys = make([]int, 0, len(mymap))tahsislerden kurtulacak ama yine de daha yavaş olacağını umuyorum.
Diğer yanıtlarda açıklanan üç yöntem üzerinde kabataslak bir karşılaştırma yaptım.
Açıkça, tuşları çekmeden önce dilimi önceden ayırmak ing'den daha hızlıdır append, ancak şaşırtıcı bir şekilde reflect.ValueOf(m).MapKeys()yöntem, ikincisinden önemli ölçüde daha yavaştır:
❯ go run scratch.go
populating
filling 100000000 slots
done in 56.630774791s
running prealloc
took: 9.989049786s
running append
took: 18.948676741s
running reflect
took: 25.50070649s
İşte kod: https://play.golang.org/p/Z8O6a2jyfTH (oyun alanında çalıştırmak çok uzun sürdüğünü iddia ederek iptal ediyor, bu yüzden, yerel olarak çalıştırın.)
keysAppendişlev sen kapasitesini ayarlayabilirsiniz keysile dizide make([]uint64, 0, len(m))büyük ölçüde benim için fonksiyonun performansını değiştirdi.
Https://play.golang.org/p/dx6PTtuBXQW adresini ziyaret edin
package main
import (
"fmt"
"sort"
)
func main() {
mapEg := map[string]string{"c":"a","a":"c","b":"b"}
keys := make([]string, 0, len(mapEg))
for k := range mapEg {
keys = append(keys, k)
}
sort.Strings(keys)
fmt.Println(keys)
}