8

给定带有嵌套文档的哈希:

myHash = {
  "MemberId"=>"ABC0001", 
  "MemberName"=>"Alan", 
  "details"=>[
    {"LineNumber"=>"4.1", "Item"=>"A0001", "Description"=>"Apple"}, 
    {"LineNumber"=>"5.1", "Item"=>"A0002"}, 
    {"LineNumber"=>"6.1", "Item"=>"Orange"}
  ]
}

我想改变它,使它看起来像:

{
  "memberid"=>"ABC0001", 
  "membername"=>"Alan", 
  "details"=>[
    {"linenumber"=>"4.1", "item"=>"A0001", "description"=>"Apple"}, 
    {"linenumber"=>"5.1", "item"=>"A0002"}, 
    {"linenumber"=>"6.1", "item"=>"Orange"}
  ]
}

换句话说,我想在哈希键中更改为小写。我知道我必须遍历哈希并使用小写方法。如果在红宝石中有任何简单的方法可以做到这一点?

4

6 回答 6

12

你可以简单地做

hash.transform_keys(&:downcase)

将哈希键更改为小写。

你可以参考我的答案https://stackoverflow.com/a/54090178/8247133

于 2019-01-08T10:50:22.980 回答
5
class Hash
  def downcase_key
    keys.each do |k|
      store(k.downcase, Array === (v = delete(k)) ? v.map(&:downcase_key) : v)
    end
    self
  end
end

myHash.downcase_key
于 2013-06-08T12:48:26.767 回答
3
def f h
  Hash[h.map{|k,v| v.class == Array ? [k,v.map{|r| f r}.to_a] : [k.downcase,v]}]
end

证明

于 2013-06-08T12:53:37.320 回答
3

我将首先创建一个方法Hash,允许您将键映射到新值:

class Hash
  def map_keys! &blk
    keys.each do |k|
      new_k = blk.call(k)
      self[new_k] = delete(k)
    end
    self
  end

  def map_keys &blk
    dup.map_keys!(&blk)
  end
end

您现在可以使用小写第一级

myHash.map_keys!(&:downcase)

myHash现在包含:

{"details"=>
  [{"LineNumber"=>"4.1", "Item"=>"A0001", "Description"=>"Apple"},
   {"LineNumber"=>"5.1", "Item"=>"A0002"},
   {"LineNumber"=>"6.1", "Item"=>"Orange"}],
 "memberid"=>"ABC0001",
 "membername"=>"Alan"}

嵌套的哈希值可以用

myHash['details'].each{|h| h.map_keys!(&:downcase) }

myHash现在包含:

{"details"=>
  [{"linenumber"=>"4.1", "item"=>"A0001", "description"=>"Apple"},
   {"linenumber"=>"5.1", "item"=>"A0002"},
   {"linenumber"=>"6.1", "item"=>"Orange"}],
 "memberid"=>"ABC0001",
 "membername"=>"Alan"}
于 2013-06-08T12:56:09.923 回答
1

我今天在解决同样的问题时找到了这个解决方案。

def lowercase_keys(h)
  new_h = { }
  h.each_pair do |k, v|
    new_k = deep_lowercase(k, true)
    new_v = deep_lowercase(v, false)
    new_h[new_k] = new_v
  end
  new_h
end

def deep_lowercase(object, with_strings)
  case object
    when String then
      with_strings ? object.downcase : object
    when Hash then
      lowercase_keys(object)
    else
      object.respond_to?(:map) ? object.map { |e| deep_lowercase(e, false) } : object
  end
end

从我的测试来看,无论哈希是值还是键本身,还是嵌入在 Enumerable 中,它都有效。

于 2014-09-23T21:52:44.310 回答
0

这是一个递归下降到任何任意嵌套的枚举并将找到的任何哈希键小写的函数:

data = {
  "MemberId"=>"ABC0001", 
  "MemberName"=>"Alan", 
  "details"=>[
    {"LineNumber"=>"4.1", "Item"=>"A0001", "Description"=>"Apple"}, 
    {"LineNumber"=>"5.1", "Item"=>"A0002"}, 
    {"LineNumber"=>"6.1", "Item"=>"Orange"}
  ]
}

def downcase_hash_keys(h)
  if h.is_a?(Hash)
    h.keys.each do |key|
      new_key = key.to_s.downcase
      h[new_key] = h.delete(key)
      downcase_hash_keys(h[new_key])
    end
  elsif h.respond_to?(:each)
    h.each { |e| downcase_hash_keys(e) }
  end
  h
end

downcase_hash_keys(data)
p data


# => {"memberid"=>"ABC0001", "membername"=>"Alan", "details"=>[{"linenumber"=>"4.1", "item"=>"A0001", "description"=>"Apple"}, {"linenumber"=>"5.1", "item"=>"A0002"}, {"linenumber"=>"6.1", "item"=>"Orange"}]}

它有点难看,因为它改变了数据结构;理想情况下,将创建一个新的哈希。但它达到了预期的效果。

于 2013-06-08T20:01:59.380 回答