说我有一系列哈希像这样:
items = [
{:user=>1, :amount=>484},
{:user=>2, :amount=>0},
{:user=>3, :amount=>8633}
]
要获得用户的amount
,我会这样:
items.select{|key| key[:user] == 1 }.first[:amount]
但是如果没有具有给定ID的user
,那么这不起作用:
> items.select{|key| key[:user] == 8 }.first[:amount]
# NoMethodError: undefined method `[]' for nil:NilClass
那么,如果找到该项目,如何返回amount
,如果没有,则返回0
?
答案 0 :(得分:4)
首先,您可以使用find
代替select
,因为您只想要第一场比赛。如果你想要一个单行,你可以这样做:
(items.find { |key| key[:user] == 8 } || { :amount => 0 })[:amount]
如果您碰巧让Rails或ActiveSupport蠢蠢欲动,那么您可以使用try
和to_i
(同时记住nil.to_i == 0
),如下所示:
items.find { |k| key[:user] == 1 }.try(:fetch, :amount).to_i
try
只调用一种方法(在这种情况下为fetch
)但如果接收方为nil
则始终返回nil
,因此nil.try(:fetch, :amount)
为nil
但是some_hash.try(:fetch, :amount)
是some_hash.fetch(:amount)
,它是一个方便的工具,可以吞没nil
而无需添加一堆额外的条件。 AFAIK,andand
gem做类似的事情而不需要所有的ActiveSupport。
答案 1 :(得分:1)
三种方式:
<强>#1 强>
def my_method(user, items)
items.each {|h|
return h[:amount] if h.key?(:user) && h[:user] == user && h.key?(:amount)}
0
end
my_method(1, items) #=> 484
my_method(5, items) #=> 0
<强>#2 强>
def my_method(user, items)
items.reduce(0) { |v,h|
(h.key?(:user) && h[:user] == user && h.key?(:amount)) ? h[:amount] : v }
end
<强>#3 强>
def my_method(user, items)
hash = items.find { |h| h.key?(:user) && h[:user] == user) }
(hash && hash.key?(:amount)) ? hash[:amount] : 0
end
答案 2 :(得分:1)
您可以捕获异常NoMethodError
begin
#code you want to execute
rescue NoMethodError
puts "0"
end
答案 3 :(得分:0)
将救援0 放在最后
items.select{|key| key[:user] == 8 }.first[:amount] rescue 0
答案 4 :(得分:0)
这是使用一些内置Ruby回退机制的变体
items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
首先,从行的末尾开始fetch
,它返回提供的散列键的值。使fetch
与使用常规哈希方括号不同的一点是,如果键不存在,fetch
将作为键错误而不是返回nil
。这是一个巧妙的技巧,但另一个有用的东西是它可以采用一个可选的第二个参数,如果找不到该键,则返回默认值:
test = { a: 1, b:2 }
test[:c] #=> nil
test.fetch(:c) #=> raise KeyError
test.fetch(:c, 0) #=> 0
方便,但你不能在nil上调用fetch
,如果它找不到任何内容,这是find
的默认回复。
幸运的是,find
也允许您指定默认返回值而不是nil。您可以传递响应call
的对象,该对象将指定如何处理没有匹配的查找。
这是一个简短的lambda,返回一个空哈希:->{{}}
,在这里它作为第一个参数传递给find
,在通常的块之前
items.find(->{{}}){ |key| key[:user] == 8 } #=> {}
所有在一起:items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
- 现在find
将始终返回某种哈希值,它将响应fetch
,如果缺少某个键,则fetch可以返回默认值。< / p>