Building a hash in a conditional way

后端 未结 11 830
梦如初夏
梦如初夏 2021-02-01 01:29

I am using Ruby on Rails 3.0.10 and I would like to build an hash key\\value pairs in a conditional way. That is, I would like to add a key and its related value if a condition

相关标签:
11条回答
  • 2021-02-01 02:00

    Using fetch can be useful if you're populating a hash from optional attributes somewhere else. Look at this example:

    def create_watchable_data(attrs = {})
      return WatchableData.new({
        id:             attrs.fetch(:id, '/catalog/titles/breaking_bad_2_737'),
        titles:         attrs.fetch(:titles, ['737']),
        url:            attrs.fetch(:url, 'http://www.netflix.com/shows/breaking_bad/3423432'),
        year:           attrs.fetch(:year, '1993'),
        watchable_type: attrs.fetch(:watchable_type, 'Show'),
        season_title:   attrs.fetch(:season_title, 'Season 2'),
        show_title:     attrs.fetch(:id, 'Breaking Bad')
      })
    end
    
    0 讨论(0)
  • 2021-02-01 02:03

    Same idea as Chris Jester-Young, with a slight readability trick

    def cond(x)
      condition ? x : :delete_me
    end
    
    hash = {
      :key1 => value1,
      :key2 => cond(value2),
      :key3 => value3
    }
    

    and then postprocess to remove the :delete_me entries

    0 讨论(0)
  • 2021-02-01 02:04

    A functional approach:

    hash = {
      :key1 => 1,
      :key2 => (2 if condition),
      :key3 => 3,
    }.compact 
    

    If Hash.compact is not available in your environment, write .reject { |k, v| v.nil? }

    0 讨论(0)
  • 2021-02-01 02:05

    I prefer tap, as I think it provides a cleaner solution than the ones described here by not requiring any hacky deleting of elements and by clearly defining the scope in which the hash is being built.

    It also means you don't need to declare an unnecessary local variable, which I always hate.

    In case you haven't come across it before, tap is very simple - it's a method on Object that accepts a block and always returns the object it was called on. So to build up a hash conditionally you could do this:

    Hash.new.tap do |my_hash|
      my_hash[:x] = 1 if condition_1
      my_hash[:y] = 2 if condition_2
      ...
    end
    

    There are many interesting uses for tap, this is just one.

    0 讨论(0)
  • 2021-02-01 02:09

    Probably best to keep it simple if you're concerned about readability:

    hash = {}
    hash[:key1] = value1
    hash[:key2] = value2 if condition?
    hash[:key3] = value3
    ...
    
    0 讨论(0)
  • 2021-02-01 02:10

    IF you build hash from some kind of Enumerable data, you can use inject, for example:

    raw_data.inject({}){ |a,e| a[e.name] = e.value if expr; a }
    
    0 讨论(0)
提交回复
热议问题