ChatGPT解决这个技术问题 Extra ChatGPT

如何用另一个键替换散列键

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

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

我希望这个哈希为

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

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

这可能会帮助您:stackoverflow.com/questions/4044451/…
+1 有用的问题
@a5his :我很高兴它有帮助 :)

g
gayavat
hash[:new_key] = hash.delete :old_key

救了我几个LOC,爱它!
我经常不喜欢“智能”的 ruby 代码,因为它需要一些时间才能知道它到底在做什么。另一方面,您的解决方案简单且具有描述性。
这确实应该是公认的答案!简单,干净,直截了当!
这个答案很优雅,但实际上并没有回答这个问题。该帖子指出需要替换的键是未知的......我们只知道它们以下划线开头,我们不知道键实际上是什么。
所以这会创建一个新的键/值对,您可以在其中指定新键并从 hash.delete :old_key 返回的值中获取值,并且删除使用旧键。哇,我想把它纹在某个地方:-D 谢谢
g
gayavat

rails Hash 有标准的方法:

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

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

UPD:红宝石2.5方法


这是 Rails 方法,不是标准的。不过答案很好。
此外,此方法不能递归地使用哈希键。
deep_transform_keys 可以用于它:) apidock.com/rails/v4.2.1/Hash/deep_transform_keys
最后!这正是我搜索的内容!
这是 Ruby 2.5 语言的标准部分:docs.ruby-lang.org/en/trunk/Hash.html#method-i-transform_keys
m
mu is too short

如果所有键都是字符串并且它们都具有下划线前缀,那么您可以使用以下方法修补散列:

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 }

没有下划线前缀的键应该没问题,无需额外修改。


你的回答有效,但病房后我发现很少有这样的哈希
{"_id"=>"4de7140772f8be03da000018", "_type"=>"WorkStation", "created_at"=>"2011-06-02T10:24:35+05:45", "input_header_ids"=>[], "line_id "=>"4de7140472f8be03da000017", "updated_at"=>"2011-06-02T10:24:35+05:45"}
{"id"=>"4de7140772f8be03da000018", "type"=>"WorkStation", "reated_at"=>"2011-06-02T10:24:35+05:45", "nput_header_ids"=>[], "ine_id "=>"4de7140472f8be03da000017", "pdated_at"=>"2011-06-02T10:24:35+05:45"}
@Manish:我确实说过“如果所有键都是字符串并且它们都具有下划线前缀”。我在更新中为您的“没有下划线前缀的键”提供了一个示例方法。
@Manish:“k”代表“key”,“v”代表“value”,“x”代表“我不知道该怎么称呼它,但我受过数学训练,所以我称之为 x”。
S
Sadiksha Gautam

你可以做

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

这应该适用于您的情况!


S
Swapnil Chincholkar

如果我们想重命名哈希中的特定键,那么我们可以这样做:
假设我的哈希是 my_hash = {'test' => 'ruby hash demo'}
现在我想用 'message' 替换 'test',那么:
{ 2}


您的答案如何解决我的问题?如果您认为这有帮助,那么您可以在问题下方的评论中添加。我的问题不是用另一个键替换一个键,你给出的解决方案是非常基本的 Hash 属性。就我而言,它不是:hash[:new_key] = has[:old_key],而是:hash[:dynamic_key] = hash[:_dynamic_key],这是关于正则表达式的明确问题,而不是简单的哈希替换。
我通过谷歌搜索找到了这个并想要@Swapnil 的答案。谢谢
D
DigitalRoss
h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }

我喜欢您尝试使用正则表达式正确过滤掉下划线,但您应该知道,在 ruby 中,与 javascript 和其他语言不同,/^/ 表示“字符串或行的开头”,而 /$/ 表示“结束字符串或线'。在这种情况下,键中不太可能有换行符,但您应该知道,在 ruby 中使用这两个运算符不仅容易出错,而且在针对注入的验证中使用错误时也非常危险。有关说明,请参见 here。希望你不介意传播意识。
Y
Yurii Verbytskyi

对于具有 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"}

非常感激!
m
maerics
hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}

C
CTS_AE

我矫枉过正,想出了以下内容。我这样做的动机是附加到散列键以避免在合并/展平散列时发生范围冲突。

例子

扩展哈希类

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


p
purushothaman poovai

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

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

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


R
Repolês

准确回答所问的问题:

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


s
stcho

如果你在哈希里面有一个哈希,比如

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