Qu'est-ce qu'une version plus courte de ceci?:
from = hash.fetch(:from)
to = hash.fetch(:to)
name = hash.fetch(:name)
# etc
Notez le fetch
, je veux soulever une erreur si la clé n'existe pas.
Il doit y en avoir une version plus courte, comme:
from, to, name = hash.fetch(:from, :to, :name) # <-- imaginary won't work
Il est possible d'utiliser ActiveSupport si nécessaire.
Utilisez Hash's values_at
méthode:
from, to, name = hash.values_at(:from, :to, :name)
Cela renverra nil
pour toutes les clés qui n'existent pas dans le hachage.
Ruby 2.3 présente enfin le fetch_values
méthode pour les hachages qui permet directement ceci:
{a: 1, b: 2}.fetch_values(:a, :b)
# => [1, 2]
{a: 1, b: 2}.fetch_values(:a, :c)
# => KeyError: key not found: :c
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
my_array = {from: 'Jamaica', to: 'St. Martin'}.values_at(:from, :to, :name)
my_array.keys.any? {|key| element.nil?} && raise || my_array
Cela générera une erreur comme vous l'avez demandé
my_array = {from: 'Jamaica', to: 'St. Martin', name: 'George'}.values_at(:from, :to, :name)
my_array.keys.any? {|key| element.nil?} && raise || my_array
Cela renverra le tableau.
Mais OP a demandé d'échouer sur une clé manquante ...
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
Vous pouvez initialiser votre hachage avec une valeur par défaut d'objet KeyError
. Cela retournera une instance de KeyError si la clé que vous essayez de récupérer n'est pas présente. Tout ce que vous devez faire est alors de vérifier sa classe (value) et de l'augmenter si c'est une KeyError.
hash = Hash.new(KeyError.new("key not found"))
Ajoutons quelques données à ce hachage
hash[:a], hash[:b], hash[:c] = "Foo", "Bar", nil
Enfin, regardez les valeurs et déclenchez une erreur si la clé n'est pas trouvée
hash.values_at(:a,:b,:c,:d).each {|v| raise v if v.class == KeyError}
Cela déclenchera une exception si et seulement si la clé n'est pas présente. Il ne se plaindra pas si vous avez une clé avec une valeur nil
.
La chose la plus simple que j'opterais serait
from, to, name = [:from, :to, :name].map {|key| hash.fetch(key)}
Alternativement, si vous souhaitez utiliser values_at
, vous pouvez utiliser un Hash
avec un bloc de valeur par défaut:
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
Ou, si vous êtes si enclin, patch de singe Hash
class ::Hash
def fetch_all(*args)
args.map {|key| fetch(key)}
end
end
from, to, name = hash.fetch_all :from, :to, :name