2012-04-12 35 views

Trả lời

15

Tuy nhiên, một giải pháp khác sẽ be:

def m1 = [ a:1, b:2 ] 
def m2 = [ b:1, c:3 ] 

def newMap = [m1,m2]*.keySet().flatten().unique().collectEntries { 
    [ (it): [m1,m2]*.get(it).findAll().sum() ] 
} 

Lấy epidemian's answer như inspiriation, bạn cũng có thể viết một phương pháp để xử lý nhiều bản đồ

def m1 = [a: 1, b: 2] 
def m2 = [b: 1, c: 3] 

def combine(Map... m) { 
    m.collectMany { it.entrySet() }.inject([:]) { result, e -> 
    result << [ (e.key):e.value + (result[ e.key ] ?: 0) ] 
    } 
} 

def newMap = combine(m1, m2) 
+3

Tôi nghĩ cung cấp một phương pháp hoàn chỉnh với một chữ ký đẹp như ví dụ thứ hai của bạn (thay vì biểu hiện được ném trong không khí) thực sự thêm một chút vào chất lượng tổng thể của phản hồi, bởi vì đó là cách chúng ta nên viết những loại điều này trong mã "thực" nếu chúng ta lo lắng về chất lượng mã. +1 = D – epidemian

2

Tôi không nghĩ rằng có một phương pháp làm sẵn cho điều này, có lẽ sử dụng một cái gì đó như:

def m1 = [a: 1, b: 2] 
def m2 = [b: 1, c: 3] 
def newMap = (m1.keySet() + m2.keySet()).inject([:]) { 
    acc, k -> acc[k] = (m1[k] ?: 0) + (m2[k] ?: 0); acc 
} 
0

này làm nó:

Map additionJoin(Map map1, Map map2) 
{ 
    def result = [:]; 
    result.putAll(map1); 
    result.putAll(map2); 

    result.each { key, value -> 
    if(map1[key] && map2[key]) 
    { 
     result[key] = map1[key] + map2[key] 
    } 
    } 

    return result; 
} 

def a = [a: 1, b: 2] 
def b = [b:1,c:3] 

def c = additionJoin(a, b) 

println c 
13

này nên làm việc cho bất kỳ số lượng bản đồ:

def maps = [[a: 1, b: 2], [b:1, c:3]] 

def result = [:].withDefault{0} 
maps.collectMany{ it.entrySet() }.each{ result[it.key] += it.value } 

assert result == [a: 1, b: 3, c: 3] 

Khái niệm maps.collectMany{ it.entrySet() } trả về một danh sách các mục bản đồ, như [a=1, b=2, b=1, c=3], và sau đó mỗi người trong số đó được thêm vào kết quả.

Một tùy chọn khác, nếu bạn muốn giữ tất cả biến đổi thành một biểu thức và làm cho nó "thêm chức năng", trước tiên hãy nhóm các mục theo khóa và sau đó tổng hợp các giá trị, nhưng tôi nghĩ nó ít có thể đọc được:

def result = maps.collectMany{ it.entrySet() } 
    .groupBy{ it.key } 
    .collectEntries{[it.key, it.value.sum{ it.value }]} 

phần groupBy trả về một bản đồ có dạng [a:[a=1], b:[b=2, b=1], c:[c=3]] và sau đó là collectEntries biến đổi mà bản đồ vào nhau mà có Kays tương tự nhưng có tổng các danh sách trong các giá trị thay thế.

+0

+1 sử dụng tốt đẹp của 'collectMany' (lấy cảm hứng từ tôi để viết phương pháp vararg) –

+0

Tuyệt vời! Tôi thích cách mà "kết hợp" phương pháp trông. Điều này hoàn toàn không có chủ đề và không liên quan nhưng, không phải là điều kỳ lạ khi viết các chuỗi cuộc gọi như 'foo.bar {...} .baz {...} 'có nên có một khoảng trống giữa tên phương thức và dấu ngoặc nhọn mở của kết thúc chứ không phải giữa dấu ngoặc nhọn đóng và toán tử dấu chấm tiếp theo? Tôi nghĩ rằng nó trông kỳ lạ khi viết câu trả lời của tôi, vì vậy tôi loại bỏ không gian đầu tiên, nhưng nó không nhìn quá tốt ... – epidemian

+0

Vâng, đó là vì dấu ngoặc đơn là tùy chọn nếu tham số cuối cùng của một phương thức là một đóng ... khó để có được nó đẹp đôi khi ;-) –

3

Một cách tốt đẹp là nó sử dụng toán tử lây lan:

def m1 = [ a:1, b:2 ] 
def m2 = [ b:1, c:3 ] 
def m3 = [ *:m1, *:m2 ] 

println "m1 = $m1" 
println "m2 = $m2" 
println "m3 = $m3" 

* Credit: http://mrhaki.blogspot.ch/2009/09/groovy-goodness-spread-operator.html

Đoạn mã trên không hoạt động trong groovysh nhưng nó là tốt trong giao diện điều khiển groovy. (Đối với phiên bản 1.8)

+2

Xin lỗi, tôi đã không nhận thấy rằng ông muốn áp dụng tổng số trong các giá trị của bản đồ. – Enio

4

Ví dụ dưới đây trình bày thêm hai bản đồ, một bản đồ thứ ba m3:

Map m1 = [ a:1, b:2 ]; 
Map m2 = [ b:1, c:3 ]; 
Map m3 = [:]; 
m3 << m1 
m3 << m2 
+0

Có vẻ như đã trả lời mà không đọc câu hỏi. Anh ta muốn thêm giá trị từ cả hai bản đồ nếu khóa là ánh xạ. Nó không trả lời câu hỏi – Rao

+0

Bạn không thể đổ lỗi cho anh ta khi tiêu đề rất khó hiểu! –

0
def merge(map1, map2) { 
    def add = { map, entry -> map << entry } 
    map2.inject(map1.inject([:], add), add) 
} 
+0

Có thể một số thông tin khác? – Loko

+0

Điều này không trả lời được câu hỏi. Mất khóa 'a' và không thêm giá trị từ cả hai bản đồ cho khóa' b' – Rao

Các vấn đề liên quan