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

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

我想让这个散列

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

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


当前回答

如果所有的键都是字符串,并且都有下划线前缀,那么你可以用这个来修补哈希:

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

Or

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 }

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

其他回答

对于Ruby 2.5或更新版本,使用transform_keys和delete_prefix / delete_suffix方法:

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.inject({}){|option, (k,v) | option["id"] = v if k == "_id"; option}

这应该对你的情况有用!

如果所有的键都是字符串,并且都有下划线前缀,那么你可以用这个来修补哈希:

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

Or

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 }

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

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

准确地回答了问题:

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