2010-09-25 38 views
153

Với tôi có số khách hàng bên dưới băm, có cách nhanh chóng (không cần phải viết tập lệnh nhiều dòng) để lấy khóa cho tôi muốn khớp với client_id? Ví dụ. Cách lấy khóa cho client_id == "2180"?Cách tìm khóa băm có chứa giá trị phù hợp

clients = { 
    "yellow"=>{"client_id"=>"2178"}, 
    "orange"=>{"client_id"=>"2180"}, 
    "red"=>{"client_id"=>"2179"}, 
    "blue"=>{"client_id"=>"2181"} 
} 

Trả lời

144

Bạn có thể sử dụng Enumerable#select:

clients.select{|key, hash| hash["client_id"] == "2180" } 
#=> [["orange", {"client_id"=>"2180"}]] 

Lưu ý rằng kết quả sẽ là một mảng của tất cả các giá trị phù hợp, nơi đây từng là một mảng của khóa và giá trị.

+0

Điều này cũng hoạt động! – Coderama

+18

@Coderama Sự khác biệt giữa 'find' và' select' là 'find' trả về kết quả trùng khớp đầu tiên và' select' (được đặt tên là 'findAll') trả về tất cả các kết quả phù hợp. –

+0

Tôi thấy, vì vậy đây sẽ là tùy chọn an toàn hơn cho các trường hợp có nhiều hơn một kết quả phù hợp. – Coderama

9

thử điều này:

clients.find{|key,value| value["client_id"] == "2178"}.first 
+1

Điều này làm việc tuyệt vời – Coderama

+4

Điều này sẽ ném một ngoại lệ nếu tìm trả về nil, bởi vì bạn không thể gọi .first trên nil. – Schrockwell

+1

Nếu sử dụng Rails, bạn có thể sử dụng '.ry (: first)' thay vì '.first' để tránh ngoại lệ (Nếu bạn đang mong đợi nó có thể cho giá trị bị thiếu). –

323

của Ruby 1,9 và lớn:

hash.key(value) => key 

Ruby 1,8:

Bạn có thể sử dụng hash.index

hsh.index(value) => key

Trả về khóa cho giá trị đã cho. Nếu không tìm thấy , trả lại nil.

h = { "a" => 100, "b" => 200 }
h.index(200) #=> "b"
h.index(999) #=> nil

Vì vậy, để có được "orange", bạn chỉ có thể sử dụng:

clients.key({"client_id" => "2180"}) 
+1

Tôi nhận được không khi tôi chạy ... – Coderama

+0

@Coderama Tôi không: http://codepad.org/2JpX9ei5 – Aillyn

+2

Điều này sẽ trở nên lộn xộn nếu băm có nhiều khóa, bởi vì bạn cần phải cung cấp toàn bộ băm thành 'chỉ mục'. –

46

Bạn có thể đảo ngược băm. clients.invert["client_id"=>"2180"] lợi nhuận "orange"

+3

Điều này cũng có vẻ giống như một cách thông minh (vì nó ngắn) để làm điều đó! – Coderama

+0

đây là những gì tôi cần cho mảng biểu mẫu (cho các hộp chọn) tạo ra một băm ngược –

21

Bạn có thể sử dụng hashname.key (valuename)

Hoặc, một đảo ngược có thể theo thứ tự. new_hash = hashname.invert sẽ cung cấp cho bạn new_hash cho phép bạn thực hiện những việc truyền thống hơn.

+3

Đây là cách thích hợp để làm điều đó trong các phiên bản gần đây (1.9+) của Ruby. –

+0

'# invert' là một ý tưởng thực sự tồi trong trường hợp này, vì bạn chủ yếu phân bổ bộ nhớ cho đối tượng băm đã ném chỉ để tìm kiếm khóa. Tùy thuộc vào kích thước băm nó có tác động hiệu suất nghiêm trọng –

3

Từ các tài liệu:

  • (? Object) phát hiện (ifnone = nil) {| obj | ...}
  • (Đối tượng?) Tìm (ifnone = nil) {| obj | ...}
  • (Object) phát hiện (ifnone = nil)
  • (Object) tìm (ifnone = nil)

Passes mỗi mục trong enum chặn. Trả về giá trị đầu tiên cho khối nào không sai. Nếu không có đối tượng nào phù hợp, hãy gọi ifnone và trả về kết quả của nó khi nó được chỉ định, hoặc trả về nil nếu không.

Nếu không có khối nào được cung cấp, thay vào đó, một điều tra viên được trả về.

(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil 
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35 

này đã làm việc cho tôi:

clients.detect{|client| client.last['client_id'] == '2180' } #=> ["orange", {"client_id"=>"2180"}] 

clients.detect{|client| client.last['client_id'] == '999999' } #=> nil 

Xem: http://rubydoc.info/stdlib/core/1.9.2/Enumerable#find-instance_method

0

Cách tốt nhất để tìm chìa khóa cho một giá trị cụ thể là sử dụng phương pháp quan trọng mà là sẵn sàng cho một băm. ...

gender = {"MALE" => 1, "FEMALE" => 2} 
gender.key(1) #=> MALE 

Tôi hy vọng nó sẽ giải quyết được vấn đề của bạn ...

1

Một cách tiếp cận tôi sẽ cố gắng là bằng cách sử dụng #map

clients.map{ |key, _| key if clients[key] == {"client_id"=>"2180"} }.compact 
#=> ["orange"] 

này sẽ trả lại tất cả lần xuất hiện của giá trị nhất định. Dấu gạch dưới có nghĩa là chúng ta không cần giá trị của khóa để được di chuyển xung quanh sao cho nó không được gán cho một biến. Mảng sẽ chứa nils nếu các giá trị không khớp nhau - đó là lý do tại sao tôi đặt #compact ở cuối.

0

Heres một cách dễ dàng để làm tìm ra chìa khóa của một giá trị nhất định:

clients = { 
     "yellow"=>{"client_id"=>"2178"}, 
     "orange"=>{"client_id"=>"2180"}, 
     "red"=>{"client_id"=>"2179"}, 
     "blue"=>{"client_id"=>"2181"} 
    } 

    p clients.rassoc("client_id"=>"2180") 

... và để tìm giá trị của một chìa khóa đưa ra:

p clients.assoc("orange") 

nó sẽ cung cấp cho bạn cặp khóa-giá trị.

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