Có cách nào đơn giản / đẹp hơn để lấy một lát chìa khóa từ bản đồ trong Go không?
Hiện tại tôi đang lặp lại trên bản đồ và sao chép các phím vào một lát:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
    keys[i] = k
    i++
}
          Có cách nào đơn giản / đẹp hơn để lấy một lát chìa khóa từ bản đồ trong Go không?
Hiện tại tôi đang lặp lại trên bản đồ và sao chép các phím vào một lát:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
    keys[i] = k
    i++
}
          Câu trả lời:
Ví dụ,
package main
func main() {
    mymap := make(map[int]string)
    keys := make([]int, 0, len(mymap))
    for k := range mymap {
        keys = append(keys, k)
    }
}
Để có hiệu quả trong Go, điều quan trọng là giảm thiểu phân bổ bộ nhớ.
mymapkhông phải là biến cục bộ (và do đó có thể tăng / thu hẹp), thì đây là giải pháp phù hợp duy nhất - nó đảm bảo rằng nếu kích thước mymapthay đổi giữa khởi tạo keysvà forvòng lặp, sẽ không có bất kỳ biến đổi nào vấn đề giới hạn.
                    Đây là một câu hỏi cũ, nhưng đây là hai xu của tôi. Câu trả lời của PeterSO ngắn gọn hơn một chút, nhưng hơi kém hiệu quả. Bạn đã biết nó sẽ lớn đến mức nào nên bạn thậm chí không cần sử dụng phụ lục:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
    keys[i] = k
    i++
}
Trong hầu hết các tình huống, nó có thể sẽ không tạo ra nhiều sự khác biệt, nhưng nó không hoạt động nhiều hơn và trong các thử nghiệm của tôi (sử dụng bản đồ với 1.000.000 int64khóa ngẫu nhiên và sau đó tạo ra các mảng khóa mười lần với mỗi phương thức), đó là về Nhanh hơn 20% để gán các thành viên của mảng trực tiếp hơn là sử dụng nối thêm.
Mặc dù cài đặt công suất sẽ loại bỏ việc phân bổ lại, việc nối thêm vẫn phải thực hiện thêm công việc để kiểm tra xem bạn đã đạt công suất trên mỗi lần nối hay chưa.
for i, k := range mymap{. Theo cách đó bạn không cần i ++?
                    i, k := range mymap, thì đó isẽ là các khóa và ksẽ là các giá trị tương ứng với các khóa đó trên bản đồ. Điều đó sẽ không thực sự giúp bạn điền vào một lát chìa khóa.
                    Bạn cũng có thể lấy một mảng các khóa với loại []Valuetheo phương thức MapKeysstruct Valuetừ gói "phản ánh":
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?
                    Một cách tốt hơn để làm điều này sẽ là sử dụng append:
keys = []int{}
for k := range mymap {
    keys = append(keys, k)
}
Ngoài ra, bạn không gặp may mắn, Go Go không phải là một ngôn ngữ rất biểu cảm.
keys = make([]int, 0, len(mymap))sẽ thoát khỏi phân bổ nhưng tôi hy vọng nó sẽ vẫn chậm hơn.
                    Tôi đã thực hiện một tiêu chuẩn sơ sài về ba phương pháp được mô tả trong các phản ứng khác.
Rõ ràng việc phân bổ trước lát cắt trước khi kéo các phím nhanh hơn appending, nhưng đáng ngạc nhiên, reflect.ValueOf(m).MapKeys()phương pháp này chậm hơn đáng kể so với phương pháp sau:
❯ 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
Đây là mã: https://play.golang.org/p/Z8O6a2jyfTH (chạy nó trong sân chơi hủy bỏ tuyên bố rằng nó mất quá nhiều thời gian, vì vậy, tốt, chạy nó cục bộ.)
keysAppendhàm của bạn , bạn có thể đặt dung lượng của keysmảng với make([]uint64, 0, len(m)), điều này đã thay đổi đáng kể hiệu năng của hàm đó đối với tôi.
                    Truy cập https://play.golang.org/p/dx6PTtuBXQW
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)
}