2012-12-26 37 views
6

Hi Tôi có một bản đồ như thế này:tìm chìa khóa trong một bản đồ, do giá trị

[this:0, is:1, a:2, file:3, anotherkey:4, aa:5] 

Tôi ước gì có thể tìm thấy những key 's trao value của bản đồ. Ví dụ: nếu giá trị 5 được cung cấp, tôi cần trả lại aa từ bản đồ.

Điều đó có khả thi không?

Trả lời

1

Có thể bạn sẽ phải lặp lại chính mình trên entry set và cố gắng tìm mục nhập với số value phù hợp.

12

Tôi không biết nếu có một phương pháp trực tiếp để có được một chìa khóa cho một giá trị nhất định, nhưng sử dụng Map#find để có được một mục bản đồ và sau đó nhận được giá trị của nó nên là đủ:

def keyForValue(map, value) { 
    map.find { it.value == value }?.key 
} 

def map = [a: 1, b: 2, c: 3] 
assert keyForValue(map, 2) == 'b' 
assert keyForValue(map, 42) == null 

Nói chung, bản đồ không cần phải có quan hệ thứ tự giữa các mục nhập của chúng, nhưng việc triển khai mặc định cho các bản đồ đen của Groovy là LinkedHashMap, mà được sắp xếp, vì vậy, keyForValue sẽ luôn mang lại khóa đầu tiên cho một giá trị khi sử dụng các bản đồ đó.

1
def expect = 5 
def m = ['this':0, is:1, a:2, file:3, aa:5] 
def r = m.collectMany{ k,v -> (v == expect) ? [k] : []} 

// Result: [aa] 
5

Không có lệnh cụ thể cho điều đó.

May mắn thay, như cho thấy here, bạn có thể dễ dàng nhận được các chìa khóa (s) cho một giá trị cụ thể trong bản đồ:

def myMap = [this:0, is:1, a:2, file:3, fix:4, aa:5] 
def myValue = 5 

Bạn có thể làm:

def myKey = myMap.find{ it.value == myValue }?.key 
// 'aa' 

Nếu bạn muốn tất cả các phím, hãy làm điều gì đó như sau:

def myMap = [this:0, is:1, a:2, file:3, fix:4, aa:5, bb:5] 
def myValue = 5 

def myKeys = [] 
myMap.findAll{ it.value == myValue }.each{myKeys << it?.key} 
// ['aa', 'bb'] 
2

Bạn có thể đảo ngược bản đồ, như sau:

Map m = [a: '1', b: '2'] 
Map mInvert = m.collectEntries { e -> [(e.value): e.key] } 

assert mInvert == ['1':'a', '2':'b'] 

assert mInvert['2'] == 'b' 
assert m['b'] == '2' 
+0

Không, mã của bạn là thú vị :) nhưng sát thủ hiệu suất vì bạn tạo lại một Bản đồ khác. Có một phương pháp để tìm một mục Map cho giá trị của nó, câu trả lời chính xác đã được đưa ra bởi epidemian thời gian dài trước đây: myMap.find {it.value == 5} .key – ARA

+0

@ARA thực sự để sử dụng lặp đi lặp lại giải pháp của crazy4groovy sẽ nhanh hơn miễn là bộ sưu tập ngược không được tái tạo mỗi lần. Bạn không nên lặp qua danh sách O (n) khi bạn có thể sử dụng bản đồ tại O (logN). Tất nhiên, hiệu suất nên có một chỗ ngồi trở lại để dễ đọc anyway - và nếu được thực hiện ngay giải pháp crazy4groovy có lẽ là dễ đọc hơn ... Tuy nhiên nó không phải là terribly "Groovy" :) –

+0

@ Bill: Có, những gì tôi nói là kẻ giết người hiệu suất là tạo lại bản đồ mỗi lần như ví dụ sử dụng lambda để tạo lại nó ngay lập tức. Tất nhiên nếu bản đồ không được tái tạo trên mỗi cuộc gọi và được duy trì, điều này sẽ nhanh hơn nhiều so với lặp lại. Đó là mục đích của Bản đồ. :) Và tôi nghĩ Bản đồ được gọi là O (1) không phải O (log (n)), một btree sẽ là O (log (n))? – ARA

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