当select没有返回时返回0?

时间:2014-04-26 01:35:03

标签: ruby arrays hash

说我有一系列哈希像这样:

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

5 个答案:

答案 0 :(得分:4)

首先,您可以使用find代替select,因为您只想要第一场比赛。如果你想要一个单行,你可以这样做:

(items.find { |key| key[:user] == 8 } || { :amount => 0 })[:amount]

如果您碰巧让Rails或ActiveSupport蠢蠢欲动,那么您可以使用tryto_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>