是否有一个很好的(一行)方式在ruby中编写一个哈希值,只有条件满足时才有一些条目?我想到了
{:a => 'a', :b => ('b' if condition)}
但如果条件未满足,则会:b == nil
。我意识到这可以在两行左右轻松完成,但在一行中会更好(例如将哈希值传递给函数时)。
我是否还缺少了另一个红宝石的惊人功能? ;)
答案 0 :(得分:50)
从Ruby 1.9+开始,如果你想根据条件构建一个哈希,你可以使用tap
,这是我最喜欢的东西。这将它分成多行,但更具可读性恕我直言:
{}.tap do |my_hash|
my_hash[:a] = 'a'
my_hash[:b] = 'b' if condition
end
答案 1 :(得分:45)
您可以先使用key =>创建哈希值nil,当条件不满足时,然后删除值为nil的那些对。例如:
{ :a => 'a', :b => ('b' if cond) }.delete_if{ |k,v| v.nil? }
收益率,对于cond == true:
{:b=>"b", :a=>"a"}
和cond == false
{:a=>"a"}
<强>更新强>
这是等效的 - 更简洁,并以ruby 1.9.3表示法:
{ a: 'a', b: ('b' if cond) }.reject{ |k,v| v.nil? }
更新Ruby 2.4 +
从ruby 2.4.0开始,您可以使用compact方法:
{ a: 'a', b: ('b' if cond) }.compact
答案 2 :(得分:23)
有兴趣看到其他答案,但这是我能想到的最好的单线(我在单线上也是出了名的坏事:P)
{:a => 'a'}.merge( condition ? {:b => 'b'} : {} )
答案 3 :(得分:20)
&gt; = Ruby 2.4:
{a: 'asd', b: nil}.compact
=> {:a=>"asd"}
答案 4 :(得分:6)
这里有很多聪明的解决方案,但IMO最简单也是最好的方法是
hash = { a: 'a', b: 'b' }
hash[:c] = 'c' if condition
这违反了OP的两行要求,但实际上其他答案看起来只是单行。让我们面对现实吧,这是最简单的解决方案,而且很容易理解。
答案 5 :(得分:4)
在Ruby 2.0中,对于数组(和位置参数),类似于旧的splat运算符(**
),有一个双splat运算符(*
)用于散列(和关键字参数)。所以你可以说:
{a: 'b', **(condition ? {b: 'b'} : {})}
答案 6 :(得分:1)
Hash[:a, 'a', *([:b, 'b'] if condition1), *([:c, 'c'] if condition2)]
这依赖于*nil
在ruby 1.9中扩展为空白的事实。在ruby 1.8中,您可能需要这样做:
Hash[:a, 'a', *(condition1 ? [:b, 'b'] : []), *(condition2 ? [:c, 'c'] : [])]
或
Hash[:a, 'a', *([:b, 'b'] if condition1).to_a, *([:c, 'c'] if condition2).to_a]
答案 7 :(得分:1)
如果你有其他人需要了解的多种条件和逻辑,那么我认为这不是一个很好的候选人。根据所需的逻辑正确创建哈希会更有意义。
答案 8 :(得分:1)
这个适用于多个条件。
(
hash = {:a => 'a'}.tap {|h|
h.store( *[(:b if condition_b), 'b'] )
h.store( *[(:c if condition_c), 'c'] )
}
).delete(nil)
请注意,我选择nil作为“垃圾”键,当你完成时它会被删除。如果您需要使用nil密钥存储实际值,只需将存储条件更改为:
(condition_b ? :b : garbage_key)
然后在最后删除(garbage_key)。
此解决方案还将保持现有的零值不变,例如如果你有:a =&gt;在原始哈希值中为nil,它不会被删除。
答案 9 :(得分:0)
hash, hash_new = {:a => ['a', true], :b => ['b', false]}, {}
hash.each_pair{|k,v| hash_new[k] = v[1] ? v : nil }
puts hash_new
答案 10 :(得分:0)
我的单线解决方案:
{:a => 'a'}.tap { |h| h.merge!(:b => 'b') if condition }
答案 11 :(得分:-4)
eval("{:a => 'a' #{', :b => \'b\'' if condition }}")
甚至
eval("{#{[":a => 'a'", (":b=>'b'" if ax)].compact.join(',')}}")
更简单的添加条件