当对象可能为空时,我该如何尝试在Ruby中迭代哈希表?

3

我发现自己经常需要这样做,当我匆忙的时候,我会用条件语句把它包起来:

if !myhash.blank?
  hash.each do |k,v|
    do_something
  end
end

或者:

myhash.map{|k,v| do_something} unless myhash.blank?

一定有更简洁的方法。


你可以使用一个“null”哈希表来设置返回一些可接受的默认值。也就是说,你可以将哈希表定义为hash = my_hash || default_hash。这样每次引用my_hash时就不需要条件语句了;只需要在第一次定义时加入条件语句即可。 - lwassink
由于空哈希是可以循环的良好值,因此您不需要使用“blank?”:if myhash - tokland
2
如果你期望一个Hash,但得到了nil,那么这是一个bug,正确的响应是修复bug,以便首先不会得到nil,而不是绕过nil!如果你“总是发现自己不得不这样做”,那么你有很多bug,你应该加强你的设计、开发、测试、代码审查和QA流程(最终,你的招聘流程,这样你就不会雇用那些一开始就写出这种愚蠢的bug的程序员)! - Jörg W Mittag
1
非常感谢您,Jorg。我在家里为我的业务编写代码。很抱歉我这么傻。但既然我们正在提供建议,我给您的建议是要改善您的礼貌。我不在乎您在SO上的得分,您的傲慢是显而易见的。 - RubyRedGrapefruit
http://imgur.com/o3fNPon - RubyRedGrapefruit
5个回答

8

我倾向于使用to_h来隐藏“是否为nil”测试:

hash.to_h.each do |k,v|
  # something
end

如果hash已经是一个哈希表,则hash.to_h等于hash,如果hash.nil?hash.to_h等于{ }
同样地,对于数组,我使用to_a
array.to_a.each { |e| ... }

to_s用于字符串,to_i用于整数(当我想将nil视为零时),...


5

我可能会选择以下两种方式之一:

(my_hash || {}).each do |k, v|
  # something
end

或者这个:
my_hash ||= {}
my_hash.each do |k, v|
  # something
end

我喜欢第一个代码片段,但不太喜欢第二个,因为重新绑定变量并不好。也许在方法的后面你需要my_hash的原始值。 - tokland

3
如果你正在使用rails,可以这样说:
my_hash.try(:each) do |key, value|
  # code
end

try方法如果在nil上调用,将返回nil或者如果接收器不响应该方法也会返回nil


3
如果你想具体迭代非空值,可以像这样操作:
hash && hash.each do |x|
  # do something
end

但我觉得unless hash.nil?更加表达清晰。


0
Hash(myhash).each {|k,v| # whatevs }

始终返回一个Hash。 修改自: https://dev59.com/kmkw5IYBdhLWcg3w2-XH#18894072

irb测试:

# $ irb
# irb(main):001:0> Hash(myhash=nil).each {|k,v|}
# => {}
# irb(main):002:0> Hash(myhash={"a" => "b"}).each {|k,v|}
# => {"a"=>"b"}

为什么要踩?“如果你认为这篇文章有待改进,请考虑添加评论。” - SoAwesomeMan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接