web-dev-qa-db-ja.com

複数のハッシュ値を一度に取得するにはどうすればよいですか?

これの短いバージョンは何ですか?:

from = hash.fetch(:from)
to = hash.fetch(:to)
name = hash.fetch(:name)
# etc

fetchに注意してください。キーが存在しない場合はエラーを発生させます。

次のような短いバージョンが必要です。

from, to, name = hash.fetch(:from, :to, :name) # <-- imaginary won't work

必要に応じてActiveSupportを使用しても構いません。

49

ハッシュの values_at メソッド:

from, to, name = hash.values_at(:from, :to, :name)

これは、ハッシュに存在しないキーに対してnilを返します。

92
Dylan Markow

Ruby 2.3はついに fetch_values これを直接達成するハッシュのメソッド:

{a: 1, b: 2}.fetch_values(:a, :b)
# => [1, 2]
{a: 1, b: 2}.fetch_values(:a, :c)
# => KeyError: key not found: :c
23
matthew.tuck
hash = {from: :foo, to: :bar, name: :buz}

[:from, :to, :name].map{|sym| hash.fetch(sym)}
# => [:foo, :bar, :buz]
[:frog, :to, :name].map{|sym| hash.fetch(sym)}
# => KeyError
3
sawa
my_array = {from: 'Jamaica', to: 'St. Martin'}.values_at(:from, :to, :name)
my_array.keys.any? {|key| element.nil?} && raise || my_array

これにより、リクエストしたようなエラーが発生します

 my_array = {from: 'Jamaica', to: 'St. Martin', name: 'George'}.values_at(:from, :to, :name)
 my_array.keys.any? {|key| element.nil?} && raise || my_array

これは配列を返します。

しかし、OPは欠落しているキーで失敗するように要求しました...

class MissingKeyError < StandardError
end
my_hash = {from: 'Jamaica', to: 'St. Martin', name: 'George'}
my_array = my_hash.values_at(:from, :to, :name)
my_hash.keys.to_a == [:from, :to, :name] or raise MissingKeyError
my_hash = {from: 'Jamaica', to: 'St. Martin'}
my_array = my_hash.values_at(:from, :to, :name)
my_hash.keys.to_a == [:from, :to, :name] or raise MissingKeyError
2
vgoff

KeyErrorオブジェクトのデフォルト値でハッシュを初期化できます。これは、取得しようとしているキーが存在しない場合、KeyErrorのインスタンスを返します。次に必要なのは、その(値の)クラスをチェックし、KeyErrorの場合に発生させることだけです。

hash = Hash.new(KeyError.new("key not found"))

このハッシュにデータを追加しましょう

hash[:a], hash[:b], hash[:c] = "Foo", "Bar", nil

最後に値を見て、キーが見つからない場合はエラーを発生させます

hash.values_at(:a,:b,:c,:d).each {|v| raise v if v.class == KeyError}

キーが存在しない場合にのみ、これは例外を発生させます。 nil値を持つキーがある場合は文句を言いません。

1
saihgala

私が行く最も簡単なことは

from, to, name = [:from, :to, :name].map {|key| hash.fetch(key)}

または、values_atを使用する場合は、Hashをデフォルト値ブロックとともに使用できます。

hash=Hash.new {|h, k| raise KeyError.new("key not found: #{k.inspect}") }
# ... populate hash
from, to, name = hash.values_at(:from, :to, :name) # raises KeyError on missing key

または、あなたがそんなに傾いているなら、猿パッチHash

class ::Hash
  def fetch_all(*args)
    args.map {|key| fetch(key)}
  end
end
from, to, name = hash.fetch_all :from, :to, :name
1