简体   繁体   English

当select不返回任何内容时返回0?

[英]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,则可以使用tryto_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM