Conditional key/value in a ruby hash

后端 未结 12 1025
天命终不由人
天命终不由人 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:21

    My one-liner solution:

    {:a => 'a'}.tap { |h| h.merge!(:b => 'b') if condition }
    
    0 讨论(0)
  • 2020-12-24 05:22

    If you have multiple conditions and logic that others will need to understand later then I suggest this is not a good candidate for a 1 liner. It would make more sense to properly create your hash based on the required logic.

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

    In Ruby 2.0 there is a double-splat operator (**) for hashes (and keyword parameters) by analogy to the old splat operator (*) for arrays (and positional parameters). So you could say:

    {a: 'b', **(condition ? {b: 'b'} : {})}
    
    0 讨论(0)
  • 2020-12-24 05:33

    >= Ruby 2.4:

    {a: 'asd', b: nil}.compact
    => {:a=>"asd"}
    
    0 讨论(0)
  • 2020-12-24 05:34

    You could first create the hash with key => nil for when the condition is not met, and then delete those pairs where the value is nil. For example:

    { :a => 'a', :b => ('b' if cond) }.delete_if{ |k,v| v.nil? }
    

    yields, for cond == true:

    {:b=>"b", :a=>"a"}
    

    and for cond == false

    {:a=>"a"} 
    

    UPDATE

    This is equivalent - a bit more concise and in ruby 1.9.3 notation:

    { a: 'a', b: ('b' if cond) }.reject{ |k,v| v.nil? }
    

    UPDATE Ruby 2.4+

    Since ruby 2.4.0, you can use the compact method:

    { a: 'a', b: ('b' if cond) }.compact
    
    0 讨论(0)
  • 2020-12-24 05:35
    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 讨论(0)
提交回复
热议问题