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

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

我想让这个散列

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

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


当前回答

如果你只想改变一个键,在Ruby 2.8+中有一个简单的方法,使用transform_keys方法。在这个例子中,如果你想改变_id为id,那么你可以:

 hash.transform_keys({_id: :id})

参考:https://bugs.ruby-lang.org/issues/16274

其他回答

你可以这样做

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

这应该对你的情况有用!

rails哈希有标准的方法:

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

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

UPD: ruby 2.5方法

如果你在一个哈希中有一个哈希,比如

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[:new_key] = hash.delete :old_key

我费尽心思想出了下面这些。这背后的动机是附加到哈希键,以避免合并在一起/平坦哈希时范围冲突。

例子

扩展哈希类

将rekey方法添加到哈希实例。

# 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?!"}

扁平化和添加“范围”

如果你传递一个散列回rekey,它将合并散列,这允许你平展集合。这允许我们在扩展散列时为键添加作用域,以避免在合并时覆盖键。

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