Conditional key/value in a ruby hash

后端 未结 12 1024
天命终不由人
天命终不由人 2020-12-24 04:41

Is there a nice (one line) way of writing a hash in ruby with some entry only there if a condition is fulfilled? I thought of

{:a => \'a\', :b => (\'b\         


        
相关标签:
12条回答
  • 2020-12-24 05:11
    eval("{:a => 'a' #{', :b => \'b\'' if condition }}")
    

    or even

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

    for more simple add conditions

    0 讨论(0)
  • 2020-12-24 05:12
    Hash[:a, 'a', *([:b, 'b'] if condition1), *([:c, 'c'] if condition2)]
    

    This relies on the fact that *nil expands to vacuity in ruby 1.9. In ruby 1.8, you might need to do:

    Hash[:a, 'a', *(condition1 ? [:b, 'b'] : []), *(condition2 ? [:c, 'c'] : [])]
    

    or

    Hash[:a, 'a', *([:b, 'b'] if condition1).to_a, *([:c, 'c'] if condition2).to_a]
    
    0 讨论(0)
  • 2020-12-24 05:14

    Interested in seeing other answers, but this is the best I can think up of for a one-liner (I'm also notoriously bad at one-liners :P)

    {:a => 'a'}.merge( condition ? {:b => 'b'} : {} )
    
    0 讨论(0)
  • 2020-12-24 05:14

    There's a lot of clever solutions in here, but IMO the simplest and therefore best approach is

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

    It goes against the OP's request of doing it in two lines, but really so do the other answers that only appear to be one-liners. Let's face it, this is the most trivial solution and it's easy to read.

    0 讨论(0)
  • 2020-12-24 05:17

    From Ruby 1.9+, if you want to build a hash based on conditionals you can use tap, which is my new favourite thing. This breaks it onto multiple lines but is more readable IMHO:

    {}.tap do |my_hash| 
      my_hash[:a] = 'a'
      my_hash[:b] = 'b' if condition
    end
    
    0 讨论(0)
  • 2020-12-24 05:20

    This one is nice for multiple conditionals.

    (
      hash = {:a => 'a'}.tap {|h|
        h.store( *[(:b if condition_b), 'b'] )
        h.store( *[(:c if condition_c), 'c'] )
      }
    ).delete(nil)
    

    Note that I chose nil as the "garbage" key, which gets deleted when you're done. If you ever need to store a real value with a nil key, just change the store conditionals to something like:

    (condition_b ? :b : garbage_key)
    

    then delete(garbage_key) at the end.

    This solution will also keep existing nil values intact, e.g. if you had :a => nil in the original hash, it won't be deleted.

    0 讨论(0)
提交回复
热议问题