当select没有返回时返回0?

问题描述 投票:0回答:5

说我有一个像这样的哈希数组:

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

ruby arrays hash
5个回答
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)nilsome_hash.try(:fetch, :amount)some_hash.fetch(:amount),它是一个方便的工具吞下nils而不添加一堆额外的条件。 AFAIK,andand gem做类似的事情而不需要所有的ActiveSupport。


1
投票

您可以捕获异常NoMethodError

begin
#code you want to execute
rescue NoMethodError
puts "0"
end

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

0
投票

把救援0放在最后

items.select{|key| key[:user] == 8 }.first[:amount] rescue 0

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可以返回默认值。

© www.soinside.com 2019 - 2024. All rights reserved.