62

什么是更短的版本?:

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。

4

7 回答 7

112

使用哈希的values_at方法:

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

这将返回nil哈希中不存在的任何键。

于 2013-07-15T04:14:23.300 回答
42

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
于 2017-04-05T02:08:41.567 回答
5
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
于 2013-07-15T04:13:28.647 回答
2
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
于 2013-07-15T04:57:45.573 回答
1

我会去做的最简单的事情是

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
于 2013-07-15T05:50:04.853 回答
1

KeyError您可以使用object的默认值初始化哈希。如果您尝试获取的密钥不存在,这将返回一个 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}

当且仅当 key 不存在时,这将引发异常。如果你有一个有价值的键,它不会抱怨nil

于 2013-07-15T14:37:13.660 回答
1

模式匹配是 Ruby 2.7 中的一个实验性特性。

hash = { from: 'me', to: 'you', name: 'experimental ruby' }

hash in { from:, to:, name: }

请参阅https://rubyreferences.github.io/rubyref/language/pattern-matching.html

于 2020-12-18T17:21:22.250 回答