如何用另一个键替换哈希键

时间:2011-06-02 04:54:50

标签: ruby-on-rails ruby ruby-on-rails-3 hash

我有一个条件,我得到一个哈希

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

我希望这个哈希为

  hash = {"id"=>"4de7140772f8be03da000018", ......}

P.S :我不知道哈希中的键是什么,它们是随机的,每个键都有一个“_”前缀,我不想下划线

11 个答案:

答案 0 :(得分:646)

hash[:new_key] = hash.delete :old_key

答案 1 :(得分:120)

rails Hash有标准方法:

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

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

UPD:ruby 2.5方法

答案 2 :(得分:34)

如果所有键都是字符串并且所有键都有下划线前缀,那么您可以使用以下方法修补哈希值:

h.keys.each { |k| h[k[1, k.length - 1]] = h[k]; h.delete(k) }

除了第一个字符外,k[1, k.length - 1]位抓取所有k。如果你想要一份副本,那么:

new_h = Hash[h.map { |k, v| [k[1, k.length - 1], v] }]

或者

new_h = h.inject({ }) { |x, (k,v)| x[k[1, k.length - 1]] = v; x }

如果您不喜欢k[]表示法提取子字符串,也可以使用sub

h.keys.each { |k| h[k.sub(/\A_/, '')] = h[k]; h.delete(k) }
Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }

并且,如果只有一些键具有下划线前缀:

h.keys.each do |k|
  if(k[0,1] == '_')
    h[k[1, k.length - 1]] = h[k]
    h.delete(k)
  end
end

可以对上述所有其他变体进行类似的修改,但这两个变体:

Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }

应该可以使用没有下划线前缀而没有额外修改的键。

答案 3 :(得分:14)

你可以做到

hash.inject({}){|option, (k,v) | option["id"] = v if k == "_id"; option}

这适用于您的情况!

答案 4 :(得分:10)

h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }

答案 5 :(得分:10)

如果我们想要在哈希中重命名特定键,那么我们可以按如下方式执行:
假设我的哈希是 my_hash = {'test' => 'ruby hash demo'}
现在我想替换“测试”。通过' message',然后:
my_hash['message'] = my_hash.delete('test')

答案 6 :(得分:2)

hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}

答案 7 :(得分:1)

我矫kill过正,并提出了以下建议。我这样做的动机是将散列键附加到后面,以防止合并/展平散列时出现范围冲突。

示例

扩展哈希类

向Hash实例添加密钥更新方法。

# 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

添加示例

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..."}

修剪示例

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

整理和添加“范围”

如果您将哈希传递回给密钥,它将合并该哈希,从而使您可以展平集合。这样,我们就可以在平整哈希值时为键添加范围,以避免合并时覆盖键。

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"}
#   ]
# }

答案 8 :(得分:1)

准确回答所要求的内容:

hash = {"_id"=>"4de7140772f8be03da000018"}
hash.transform_keys { |key| key[1..] }
# => {"id"=>"4de7140772f8be03da000018"}

从Ruby 2.5版本开始,方法transform_keys存在于Hash类中。

https://blog.bigbinary.com/2018/01/09/ruby-2-5-adds-hash-transform_keys-method.html

答案 9 :(得分:1)

对于使用transform_keysdelete_prefix / delete_suffix方法的 Ruby 2.5 或更高版本:

hash1 = { '_id' => 'random1' }
hash2 = { 'old_first' => '123456', 'old_second' => '234567' }
hash3 = { 'first_com' => 'google.com', 'second_com' => 'amazon.com' }

hash1.transform_keys { |key| key.delete_prefix('_') }
# => {"id"=>"random1"}
hash2.transform_keys { |key| key.delete_prefix('old_') }
# => {"first"=>"123456", "second"=>"234567"}
hash3.transform_keys { |key| key.delete_suffix('_com') }
# => {"first"=>"google.com", "second"=>"amazon.com"}

答案 10 :(得分:0)

先前的答案足够好,但是它们可能会更新原始数据。 如果您不希望原始数据受到影响,可以尝试使用我的代码。

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

首先它将忽略键“ _id”,然后与更新的键合并。