How to replace a hash key with another key

后端 未结 11 1430
青春惊慌失措
青春惊慌失措 2020-12-04 07:36

I have a condition where, I get a hash

  hash = {\"_id\"=>\"4de7140772f8be03da000018\", .....}

and I want this hash as

         


        
相关标签:
11条回答
  • 2020-12-04 07:50

    rails Hash has standard method for it:

    hash.transform_keys{ |key| key.to_s.upcase }
    

    http://api.rubyonrails.org/classes/Hash.html#method-i-transform_keys

    UPD: ruby 2.5 method

    0 讨论(0)
  • 2020-12-04 07:50
    h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }
    
    0 讨论(0)
  • 2020-12-04 07:57
    hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}
    
    0 讨论(0)
  • 2020-12-04 08:00

    If we want to rename a specific key in hash then we can do it as follows:
    Suppose my hash is my_hash = {'test' => 'ruby hash demo'}
    Now I want to replace 'test' by 'message', then:
    my_hash['message'] = my_hash.delete('test')

    0 讨论(0)
  • 2020-12-04 08:02

    Previous answers are good enough, but they might update original data. In case if you don't want the original data to be affected, you can try my code.

     newhash=hash.reject{|k| k=='_id'}.merge({id:hash['_id']})
    

    First it will ignore the key '_id' then merge with the updated one.

    0 讨论(0)
  • 2020-12-04 08:06

    I went overkill and came up with the following. My motivation behind this was to append to hash keys to avoid scope conflicts when merging together/flattening hashes.

    Examples

    Extend Hash Class

    Adds rekey method to Hash instances.

    # Adds additional methods to Hash
    class ::Hash
      # Changes the keys on a hash
      # Takes a block that passes the current key
      # Whatever the block returns becomes the new key
      # If a hash is returned for the key it will merge the current hash 
      # with the returned hash from the block. This allows for nested rekeying.
      def rekey
        self.each_with_object({}) do |(key, value), previous|
          new_key = yield(key, value)
          if new_key.is_a?(Hash)
            previous.merge!(new_key)
          else
            previous[new_key] = value
          end
        end
      end
    end
    

    Prepend Example

    my_feelings_about_icecreams = {
      vanilla: 'Delicious',
      chocolate: 'Too Chocolatey',
      strawberry: 'It Is Alright...'
    }
    
    my_feelings_about_icecreams.rekey { |key| "#{key}_icecream".to_sym }
    # => {:vanilla_icecream=>"Delicious", :chocolate_icecream=>"Too Chocolatey", :strawberry_icecream=>"It Is Alright..."}
    

    Trim Example

    { _id: 1, ___something_: 'what?!' }.rekey do |key|
      trimmed = key.to_s.tr('_', '')
      trimmed.to_sym
    end
    # => {:id=>1, :something=>"what?!"}
    

    Flattening and Appending a "Scope"

    If you pass a hash back to rekey it will merge the hash which allows you to flatten collections. This allows us to add scope to our keys when flattening a hash to avoid overwriting a key upon merging.

    people = {
      bob: {
        name: 'Bob',
        toys: [
          { what: 'car', color: 'red' },
          { what: 'ball', color: 'blue' }
        ]
      },
      tom: {
        name: 'Tom',
        toys: [
          { what: 'house', color: 'blue; da ba dee da ba die' },
          { what: 'nerf gun', color: 'metallic' }
        ]
      }
    }
    
    people.rekey do |person, person_info|
      person_info.rekey do |key|
        "#{person}_#{key}".to_sym
      end
    end
    
    # =>
    # {
    #   :bob_name=>"Bob",
    #   :bob_toys=>[
    #     {:what=>"car", :color=>"red"},
    #     {:what=>"ball", :color=>"blue"}
    #   ],
    #   :tom_name=>"Tom",
    #   :tom_toys=>[
    #     {:what=>"house", :color=>"blue; da ba dee da ba die"},
    #     {:what=>"nerf gun", :color=>"metallic"}
    #   ]
    # }
    
    
    0 讨论(0)
提交回复
热议问题