[英]Return 0 when select returns nothing?
Say I have an array of hashes like so: 假设我有一系列的哈希值,如下所示:
items = [
{:user=>1, :amount=>484},
{:user=>2, :amount=>0},
{:user=>3, :amount=>8633}
]
To get the amount
for a user, I'd so something like this: 为了获得用户的
amount
,我会这样:
items.select{|key| key[:user] == 1 }.first[:amount]
But if there isn't a user
with a given ID, then that doesn't work: 但是,如果没有具有给定ID的
user
,那将不起作用:
> items.select{|key| key[:user] == 8 }.first[:amount]
# NoMethodError: undefined method `[]' for nil:NilClass
So how can I return amount
if it finds the item, but return 0
if there's nothing? 那么,如果找到商品我该如何退还
amount
如果什么都没有退还0
?
First of all, you can use find
instead of select
since you only want the first match. 首先,您可以使用
find
而不是select
因为您只需要第一个匹配项。 If you want a one-liner, you can do something like this: 如果您想要单线,则可以执行以下操作:
(items.find { |key| key[:user] == 8 } || { :amount => 0 })[:amount]
If you happen to have Rails or ActiveSupport kicking around then you could use try
and to_i
(while remembering that nil.to_i == 0
) like this: 如果碰巧遇到了Rails或ActiveSupport,则可以使用
try
和to_i
(同时记住nil.to_i == 0
),如下所示:
items.find { |k| key[:user] == 1 }.try(:fetch, :amount).to_i
try
just calls a method ( fetch
in this case) but always returns nil
if the receiver is nil
so nil.try(:fetch, :amount)
is nil
but some_hash.try(:fetch, :amount)
is some_hash.fetch(:amount)
, it is a handy tool for swallowing up nil
s without adding a bunch of extra conditionals. try
只调用一个方法(在这种情况下为fetch
),但如果接收方为nil
,则始终返回nil
,因此nil.try(:fetch, :amount)
为nil
但是some_hash.try(:fetch, :amount)
为some_hash.fetch(:amount)
,它是吞下了一个方便的工具, nil
无需添加额外的一堆条件语句的秒。 AFAIK, the andand
gem does similar things without requiring all the ActiveSupport. 在AFAIK中,
andand
gem不需要所有ActiveSupport即可执行类似的操作。
Three ways: 三种方式:
#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 #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 #3
def my_method(user, items)
hash = items.find { |h| h.key?(:user) && h[:user] == user) }
(hash && hash.key?(:amount)) ? hash[:amount] : 0
end
You could catch the Exception NoMethodError 您可以捕获异常NoMethodError
begin
#code you want to execute
rescue NoMethodError
puts "0"
end
将救援0放在最后
items.select{|key| key[:user] == 8 }.first[:amount] rescue 0
Here's a variant using some built-in Ruby fallback mechanisms 这是使用一些内置的Ruby后备机制的变体
items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
First, starting from the end of the line, fetch
, which returns the value at a provided hash key. 首先,从该行的末尾开始,
fetch
,它在提供的哈希键处返回该值。 One thing that makes fetch
different from using regular hash square brackets is that, if the key isn't there, fetch
throws as a key error instead of returning nil
. 使
fetch
与使用常规哈希方括号不同的一件事是,如果键不存在,则fetch
作为键错误抛出,而不是返回nil
。 That's a neat trick, but the other useful thing is that it can take an optional second argument, which is the default thing to return if that key isn't found: 这是一个巧妙的技巧,但是另一个有用的事情是它可以采用可选的第二个参数,如果找不到该键,则默认返回该参数:
test = { a: 1, b:2 }
test[:c] #=> nil
test.fetch(:c) #=> raise KeyError
test.fetch(:c, 0) #=> 0
Handy, but you can't call fetch
on nil, which is the default return for find
if it finds nothing. 方便,但是您不能在nil上调用
fetch
,这是find
的默认返回值,如果它什么也没找到。
Luckily, find
also lets you assign a default return value instead of nil. 幸运的是,
find
还可以让您分配默认的返回值,而不是nil。 You can pass an object that responds to call
, and that object will specify how to handle a find with no matches. 您可以传递一个响应
call
的对象,该对象将指定如何处理不匹配的查找。
Here's a short lambda that returns an empty hash: ->{{}}
and here it is passed as a first argument to find
, before the usual block 这是一个简短的lambda,它返回一个空哈希:
->{{}}
,在这里它作为第一个参数传递给find
,通常位于块之前
items.find(->{{}}){ |key| key[:user] == 8 } #=> {}
All together: items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
: items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
-- now find
will always return some sort of hash, which will respond to fetch
, and fetch can return a default if a key is missing. items.find(->{{}}){|e| e[:user] == 8}.fetch(:amount, 0)
-现在find
将始终返回某种哈希值,该哈希值将对fetch
作出响应,并且如果缺少键,fetch可以返回默认值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.