Bắt đầu sự kết hợp của hai bản đồ


81

Tôi có một hàm đệ quy tạo các đối tượng đại diện cho đường dẫn tệp (các khóa là đường dẫn và giá trị là thông tin về tệp). Nó đệ quy vì nó chỉ dùng để xử lý các tệp, vì vậy nếu gặp phải một thư mục, hàm sẽ được gọi một cách đệ quy trên thư mục.

Tất cả những gì đang được nói, tôi muốn làm tương đương với một liên hợp tập hợp trên hai bản đồ (tức là bản đồ "chính" được cập nhật với các giá trị từ lời gọi đệ quy). Có một cách thành ngữ nào để làm điều này ngoài việc lặp lại trên một bản đồ và gán từng khóa, giá trị trong đó cho cùng một thứ trong bản đồ kia không?

Đó là: cho a,blà loại map [string] *SomeObject, và abđược cuối cùng dân cư, là có cách nào để cập nhật avới tất cả các giá trị trong b?


2
Có lẽ bạn có thể sử dụng một thùng chứa bộ thực tế cho công việc này: github.com/deckarep/golang-set
Ralph Caraveo

Đề xuất của Ralph là tốt cho bộ. Tuy nhiên, tôi muốn nói rằng trong trường hợp của bạn, nó không phải là một liên minh nhiều vì nó là một hợp nhất ; một tập hợp chỉ nên là một tập hợp các "khóa", trong khi bạn có hai tập hợp các cặp khóa-giá trị, trong đó một "tập hợp" sẽ được ưu tiên hơn tập hợp còn lại.
ANisus

Câu trả lời:


132

Không có cách nào được xây dựng sẵn, cũng như bất kỳ phương pháp nào trong các gói tiêu chuẩn để thực hiện việc hợp nhất như vậy.

Cách bình thường là chỉ cần lặp lại:

for k, v := range b {
    a[k] = v
}

5
Để thêm vào những gì ANisus đã trả lời: Bản đồ về cơ bản là bảng băm. Có thể không có cách nào để tính toán sự kết hợp của hai bản đồ nhanh hơn chỉ đơn giản là lặp qua cả hai bản đồ.
fuz

Bạn có thể sử dụng sự phản chiếu để viết một hàm liên hợp kiểu bất khả tri, nhưng nó sẽ chậm hơn.
Evan

Mã UNION này có nên giá trị của a [k] và v trước khi gán v cho [k] không? Điều gì sẽ xảy ra nếu a [k] và v là mảng hoặc bản đồ?
vdolez

2
Anh ấy đang tìm cách kết hợp các bản đồ, không nhất thiết là các giá trị trong bản đồ. Nếu bạn muốn làm điều gì đó tương tự, bạn chỉ cần thay đổi a[k] = vthành a[k] = a[k] + vhoặc một cái gì đó tương tự.
Kyle

@Kyle Tôi nghĩ bạn đúng. Đối với liên minh thực tế , điều này có thể được sử dụng:a[k] = append(a[k], v...)
user3405291

2

Nếu bạn có một vài bản đồ lồng nhau leftright, thì hàm này sẽ thêm đệ quy các mục từ rightvào left. Nếu khóa đã có trong leftthì chúng tôi đệ quy sâu hơn vào cấu trúc và chỉ cố gắng thêm khóa vào left(ví dụ: không bao giờ thay thế chúng).


type m = map[string]interface{}

// Given two maps, recursively merge right into left, NEVER replacing any key that already exists in left
func mergeKeys(left, right m) m {
    for key, rightVal := range right {
        if leftVal, present := left[key]; present {
            //then we don't want to replace it - recurse
            left[key] = mergeKeys(leftVal.(m), rightVal.(m))
        } else {
            // key not in left so we can just shove it in
            left[key] = rightVal
        }
    }
    return left
}

LƯU Ý: Tôi không xử lý trường hợp giá trị không phải là chính nó a map[string]interface{}. Vì vậy, nếu bạn có left["x"] = 1right["x"] = 2sau đó mã trên sẽ hoảng sợ khi cố gắng leftVal.(m).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.