ruby散列中的条件键/值

问题描述 投票:46回答:12

是否有一个很好的(一行)方式在ruby中编写一个哈希值,只有条件满足时才有一些条目?我想到了

{:a => 'a', :b => ('b' if condition)}

但如果条件不满足,那就会留下:b == nil。我意识到这可以在两行左右轻松完成,但在一行中会更好(例如将哈希传递给函数时)。

我错过了(还)另一个红宝石的惊人功能吗? ;)

ruby
12个回答
44
投票

您可以首先使用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"} 

UPDATE

这是相同的 - 更简洁,并在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

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

0
投票

我的单线解决方案:

{:a => 'a'}.tap { |h| h.merge!(:b => 'b') if condition }

-4
投票
eval("{:a => 'a' #{', :b => \'b\'' if condition }}")

甚至

eval("{#{[":a => 'a'", (":b=>'b'" if ax)].compact.join(',')}}")

更简单的添加条件


50
投票

从Ruby 1.9+开始,如果你想根据条件构建一个哈希,你可以使用tap,这是我最喜欢的东西。这会将它分成多行,但更具可读性恕我直言:

{}.tap do |my_hash| 
  my_hash[:a] = 'a'
  my_hash[:b] = 'b' if condition
end

23
投票

有兴趣看到其他答案,但这是我能想到的最好的单线程(我在单线上也是出了名的坏:P)

{:a => 'a'}.merge( condition ? {:b => 'b'} : {} )

20
投票

> = Ruby 2.4:

{a: 'asd', b: nil}.compact
=> {:a=>"asd"}

6
投票

这里有很多聪明的解决方案,但IMO最简单,也是最好的方法

hash = { a: 'a', b: 'b' }
hash[:c] = 'c' if condition

它违背了OP的要求,即两行,但其他答案似乎只是单行。让我们面对现实,这是最简单的解决方案,它很容易阅读。


4
投票

在Ruby 2.0中,对于数组(和位置参数)类似于旧的splat运算符(**),有一个双splat运算符(*)用于散列(和关键字参数)。所以你可以说:

{a: 'b', **(condition ? {b: 'b'} : {})}

1
投票
Hash[:a, 'a', *([:b, 'b'] if condition1), *([:c, 'c'] if condition2)]

这依赖于*nil在红宝石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]

1
投票

如果你有其他人需要了解的多种条件和逻辑,那么我认为这不是一个很好的候选人。根据所需的逻辑正确创建哈希更有意义。


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 => nil,则不会删除它。

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