2011-09-15 31 views

Trả lời

44

Điều đó giống như một cách hoàn toàn tốt để làm điều này với tôi. Tôi không nghĩ rằng sao chép một bản đồ vào một bản đồ khác là đủ phổ biến để có một giải pháp một lớp lót.

+24

Đó là một sự xấu hổ 'copy' chỉ hoạt động trên lát. –

+16

"Tôi không nghĩ rằng sao chép một bản đồ vào một bản đồ khác là đủ phổ biến" ... đó là con vật cưng chính của tôi đi tiểu với đi. Đó là một cái gì đó thực sự dễ dàng để làm trên các loại bản địa trên tất cả các ngôn ngữ khác ra khỏi đó. –

+7

@EduFelipe Tôi đồng ý. Bản chất đặc biệt của các loại chung được xây dựng trong Go (ví dụ: bản đồ) và thiếu bất kỳ cách nào để có cùng một loại chức năng trong các loại do người dùng xác định (ví dụ: không hỗ trợ cho generics), là một trong những vấn đề lớn nhất của tôi với Go. Và nó chỉ là một trong nhiều lý do tại sao tôi yêu Rust. –

7

Sử dụng vòng lặp for range đơn giản là giải pháp hiệu quả nhất.

Lưu ý rằng nội trang dựng sẵn copy không thể chỉ sao chép bộ nhớ của src đến địa chỉ dst vì chúng có thể có bố cục bộ nhớ hoàn toàn khác. Bản đồ phát triển để chứa số lượng mục được lưu trữ trong đó. Vì vậy, ví dụ nếu bạn có một bản đồ với một triệu phần tử, nó chiếm nhiều bộ nhớ hơn một bản đồ mới được tạo mới và do đó, một built-in copy có thể không chỉ sao chép bộ nhớ mà không phân bổ mới.

Nếu bản đồ của bạn là lớn, bạn có thể tăng tốc độ sao chép các yếu tố nếu bạn có thể tạo ra các bản đồ địa điểm có công suất lớn đủ để tránh rehashing và phân bổ lại (công suất ban đầu không bị ràng buộc kích thước của nó), ví dụ:

dst := make(map[K]V, len(src)) 

for k, v := range src { 
    dst[k] = v 
} 

Nếu hiệu suất không phải là một vấn đề (ví dụ như bạn đang làm việc với bản đồ nhỏ), một giải pháp chung có thể được tạo ra bằng cách sử dụng reflect gói:

func MapCopy(dst, src interface{}) { 
    dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src) 

    for _, k := range sv.MapKeys() { 
     dv.SetMapIndex(k, sv.MapIndex(k)) 
    } 
} 

giải pháp này không kiểm tra xem các đối số được thực sự bản đồ và nếu đích đến không nil. Thử nghiệm nó:

m1 := map[int]string{1: "one", 2: "two"} 
m2 := map[int]string{} 
MapCopy(m2, m1) 
fmt.Println(m2) 

m3 := map[string]int{"one": 1, "two": 2} 
m4 := map[string]int{} 
MapCopy(m4, m3) 
fmt.Println(m4) 

Output (thử nó trên Go Playground):

map[1:one 2:two] 
map[one:1 two:2] 
2

Bạn có thể sử dụng github.com/linkosmos/mapop

input := map[string]interface{}{ 
    "Key1": 2, 
    "key3": nil, 
    "val": 2, 
    "val2": "str", 
    "val3": 4, 
} 

input2 := map[string]interface{}{ 
    "a2": "str", 
    "a3": 4, 
} 

input = mapop.Merge(input, input2) 

input{"Key1": 2, "key3": nil, "val": 2, "val2": "str", "val3": 4, "a2": "str", "a3": 4} 
Các vấn đề liên quan