我有一个条件,我得到一个哈希
hash = {"_id"=>"4de7140772f8be03da000018", .....}
我希望这个哈希为
hash = {"id"=>"4de7140772f8be03da000018", ......}
PS:我不知道哈希中的键是什么,它们是随机的,每个键都有一个“_”前缀,我不想要下划线
hash[:new_key] = hash.delete :old_key
rails Hash 有标准的方法:
hash.transform_keys{ |key| key.to_s.upcase }
http://api.rubyonrails.org/classes/Hash.html#method-i-transform_keys
UPD:红宝石2.5方法
如果所有键都是字符串并且它们都具有下划线前缀,那么您可以使用以下方法修补散列:
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 }
没有下划线前缀的键应该没问题,无需额外修改。
你可以做
hash.inject({}){|option, (k,v) | option["id"] = v if k == "_id"; option}
这应该适用于您的情况!
如果我们想重命名哈希中的特定键,那么我们可以这样做:
假设我的哈希是 my_hash = {'test' => 'ruby hash demo'}
现在我想用 'message' 替换 'test',那么:
{ 2}
hash[:new_key] = has[:old_key]
,而是:hash[:dynamic_key] = hash[:_dynamic_key]
,这是关于正则表达式的明确问题,而不是简单的哈希替换。
h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }
对于具有 transform_keys 和 delete_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"}
hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}
我矫枉过正,想出了以下内容。我这样做的动机是附加到散列键以避免在合并/展平散列时发生范围冲突。
例子
扩展哈希类
将 rekey 方法添加到 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"}
# ]
# }
以前的答案已经足够好了,但它们可能会更新原始数据。如果您不希望原始数据受到影响,可以尝试我的代码。
newhash=hash.reject{|k| k=='_id'}.merge({id:hash['_id']})
首先它将忽略键“_id”,然后与更新的键合并。
准确回答所问的问题:
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
如果你在哈希里面有一个哈希,比如
hash = {
"object" => {
"_id"=>"4de7140772f8be03da000018"
}
}
如果您想将 "_id"
更改为"token"
您可以在此处使用 deep_transform_keys
并这样做
hash.deep_transform_keys do |key|
key = "token" if key == "_id"
key
end
这导致
{
"object" => {
"token"=>"4de7140772f8be03da000018"
}
}
即使你有一个符号键散列而不是开始,比如
hash = {
object: {
id: "4de7140772f8be03da000018"
}
}
您可以结合所有这些概念将它们转换为字符串键哈希
hash.deep_transform_keys do |key|
key = "token" if key == :id
key.to_s
end
hash.delete :old_key
返回的值中获取值,并且删除使用旧键。哇,我想把它纹在某个地方:-D 谢谢