【问题标题】:how to change hash keys in the lower case using ruby如何使用 ruby​​ 更改小写的哈希键
【发布时间】:2013-06-04 16:02:05
【问题描述】:

给定带有嵌套文档的散列:

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

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

【问题讨论】:

    标签: ruby hash lowercase


    【解决方案1】:

    你可以做的很简单

    hash.transform_keys(&:downcase)
    

    将哈希键更改为小写。

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

    【讨论】:

    • 这是最好的答案。如果你有嵌套哈希,你应该使用deep_transform_keys
    【解决方案2】:
    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
    

    【讨论】:

    • 对于@cdshines,当键本身是哈希时,此代码不起作用。
    【解决方案3】:
    def f h
      Hash[h.map{|k,v| v.class == Array ? [k,v.map{|r| f r}.to_a] : [k.downcase,v]}]
    end
    

    proof

    【讨论】:

      【解决方案4】:

      我将首先在 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"}
      

      【讨论】:

      • 现在只需用一种方法将所有步骤收集在一起就可以了;)
      • 我认为编写可重用和可读的代码比将所有内容都放入单行中更重要;-)
      【解决方案5】:

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

      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
      

      从我的测试来看,无论 Hash 是 Values 还是 Keys 本身,还是嵌入到 Enumerable 中,它都有效。

      【讨论】:

        【解决方案6】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2010-09-23
          • 1970-01-01
          • 2021-12-07
          • 2011-11-24
          • 2015-08-26
          • 1970-01-01
          • 2011-07-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多