一致する値を含むハッシュキーを見つける方法


198

以下のクライアントハッシュがある場合、client_idと一致させたいキーを取得するための(複数行のスクリプトを記述せずに)簡単なルビー方法はありますか?たとえば、キーを取得する方法はclient_id == "2180"

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

回答:


176

Enumerable#selectを使用できます

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

結果は、一致するすべての値の配列になります。それぞれがキーと値の配列です。


22
差@Coderama findおよびselect即ちfind戻り最初に一致し、select(によってエイリアスされるfindAll)すべての一致を返します。
Daniel Vandersluis

なるほど、これは複数の一致がある場合の安全なオプションです。
Coderama

1
これはinvert、アイテムを見つけるためだけに(を呼び出して)まったく新しいハッシュを作成するよりも優れています。
Hejazi 2013年

3
Ruby 1.9.3以降では、一致した新しいハッシュが返されることに注意してください。Ruby <= 1.8.7使用されていたように、配列を返しません。 clients.select{|key, hash| hash["client_id"] == "2180" } # => {"orange"=>{"client_id"=>"2180"}}
AndrewS、2014年

キーを取得するには、単純にclients.select{|key, hash| hash["client_id"] == "2180" }.keys
Mirror318

407

Ruby 1.9以降

hash.key(value) => key

Ruby 1.8

あなたは使うことができます hash.index

hsh.index(value) => key

指定された値のキーを返します。見つからない場合はを返しますnil

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

したがって、を取得するには"orange"、次のように使用します。

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

2
ハッシュに複数のキーがある場合、ハッシュ全体をに渡す必要があるため、これはやや面倒になりますindex
Daniel Vandersluis、

51
Hash#index変更されHash#keyRuby 1.9の中で
Vikrant Chaudharyさん

12
これは最初の一致のみを返すことに注意してください。同じ値を持つ複数のハッシュペアリングがある場合、一致する値を持つ最初のキーが返されます。
マイクキャンベル

47

ハッシュを逆にすることができます。clients.invert["client_id"=>"2180"]戻り値"orange"


3
これは(短いので)賢い方法のようにも思えます!
コデラマ

これが、後方ハッシュを作成するフォーム配列(選択ボックス用)に必要なものです
Joseph Le Brech

22

hashname.key(valuename)を使用できます

または、反転が正しい場合もあります。new_hash = hashname.invertあなたを与えるだろうnew_hashあなたはもっと伝統的に物事を行うことができますことを。


3
これは、Rubyの最近のバージョン(1.9以降)で適切な方法です。
Lars Haugseth、2013年

#invertキーを見つけるためだけに、本質的にスローアウェイハッシュオブジェクトにメモリを割り当てているので、この場合は本当に悪い考えです。ハッシュサイズによってはパフォーマンスに重大な影響があります
Dr.Strangelove

15

これを試して:

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

4
検索でnilが返された場合は、nilで.firstを呼び出せないため、例外がスローされます。
シュロックウェル

1
Railsを使用している場合は、.try(:first)代わりに.firstを使用して例外を回避できます(値が欠落している可能性がある場合)。
aaron-coding

2
Ruby 2.3.0 +使用できる安全なナビゲーターを &.first無記号Exceptionから防ぐために、ブロックの最後に
GAGAN Gamiさん


6

ドキュメントから:

  • (オブジェクト?)detect(ifnone = nil){| obj | ...}
  • (オブジェクト?)find(ifnone = nil){| obj | ...}
  • (オブジェクト)検出(ifnone = nil)
  • (オブジェクト)find(ifnone = nil)

enumの各エントリを渡してブロックします。ブロックがfalseでない最初のものを返します。一致するオブジェクトがない場合、ifnoneを呼び出し、指定されている場合はその結果を返し、それ以外の場合はnilを返します。

ブロックが指定されていない場合は、代わりに列挙子が返されます。

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

これは私のために働きました:

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

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

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


3

特定の値のキーを見つける最善の方法は、ハッシュに使用できるキーメソッドを使用することです...

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

それがあなたの問題を解決することを願っています...


2

私が試す別のアプローチは、 #map

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

これは、指定された値のすべての出現を返します。下線は、変数に割り当てられないように、キーの値を持ち越す必要がないことを意味します。値が一致しない場合、配列にはnilが含まれます#compact。そのため、最後に配置しました。


1

与えられた値のキーを見つける簡単な方法を次に示します。

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

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

...そして与えられたキーの値を見つけるには:

    p clients.assoc("orange") 

キーと値のペアが表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.