【问题标题】:Converting "Master List" style nested array into a nested hash using Ruby使用 Ruby 将“主列表”样式的嵌套数组转换为嵌套哈希
【发布时间】:2015-11-02 18:14:59
【问题描述】:

一位朋友向我提出了一个编码挑战,我一直在努力执行它。我应该获取一个数组,并根据他的规范操作数据并构造一个自定义哈希。

起始数据

    [
        ['first_name', 'last_name', 'phone_number', 'level_of_caringness'],
        ['Phteven', 'Cartwright', 911, 'None'],
        ['Carol', 'Smellsbad', 666, 'Hateful'],
        ['Bambam', 'Idontwanttomaketheseanymore', 134, 'QWERQWER']
    ]

最终目标

{911: { first_name: "Phteven", last_name: 'Cartwright', phone_number: 911, level_of_caringness: 'None'},
 666: {first_name: "Carol", last_name: 'Smellsbad', phone_number: 666, level_of_caringness: 'Hateful'}
 134: {first_name: "Bambam", last_name: 'Idontwanttomaketheseanymore', phone_number: 134, level_of_caringness: 'QWERQWER'}

}

def array_to_hash3(array)
 keys = array.shift
 array.each_with_object({}) {|v, h| h[[array][2]] = {keys[0] => v[0], keys[1] => v[1], keys[2] => v[2], keys[3] => v[3]}}

结束

这让我着迷:

{nil=>{"first_name"=>"Bambam", "last_name"=>"Idontwanttomaketheseanymore", "phone_number"=>134, "level_of_caringness"=>"QWERQWER"}}

所以我在球场,但不完全在那里。

感谢您的意见!

编辑

我能够更接近这个

def array_to_hash3(array)
 key = array.shift
 array.each_with_object({}) {|v, h| h[v[2]] = {key[0] => v[0], key[1] => v[1], key[2] => v[2], key[3] => v[3]}}
end

结果

{911=>{"first_name"=>"Phteven", "last_name"=>"Cartwright", "phone_number"=>911, "level_of_caringness"=>"None"}, 
 666=>{"first_name"=>"Carol", "last_name"=>"Smellsbad", "phone_number"=>666, "level_of_caringness"=>"Hateful"}, 
 134=>{"first_name"=>"Bambam", "last_name"=>"Idontwanttomaketheseanymore", "phone_number"=>134, "level_of_caringness"=>"QWERQWER"}}

所以我剩下的一件事是,原始请求想要使用电话号码作为符号而不是固定数字/整数键。有什么想法吗?

编辑

终于明白了

def array_to_hash4(array)
  key = array.shift
  array.each_with_object({}) do |record, h|
    h[record[2]] = Hash[key.zip(record)]
  end
end

{
 911=>{"first_name"=>"Phteven", 
       "last_name"=>"Cartwright", 
       "phone_number"=>911, 
       "level_of_caringness"=>"None"}, 
 666=>{"first_name"=>"Carol", 
       "last_name"=>"Smellsbad", 
       "phone_number"=>666, 
       "level_of_caringness"=>"Hateful"}, 
 134=>{"first_name"=>"Bambam",                  
       "last_name"=>"Idontwanttomaketheseanymore", 
       "phone_number"=>134, 
       "level_of_caringness"=>"QWERQWER"}
}

【问题讨论】:

    标签: arrays ruby hash


    【解决方案1】:
    require 'pp'
    
    data = [
      ['first_name', 'last_name', 'phone_number', 'level_of_caringness'],
      ['Phteven', 'Cartwright', 911, 'None'],
      ['Carol', 'Smellsbad', 666, 'Hateful'],
      ['Bambam', 'Idontwanttomaketheseanymore', 134, 'QWERQWER']
    ]
    
    result = {}
    cols = data[0]
    
    data[1..-1].each do |row|
      inner_hash = {}
    
      cols.each_with_index do |col, i|
        inner_hash[col] = row[i] 
      end
    
      result[row[2].to_s.to_sym] = inner_hash
    end
    
    pp result
    
    --output:--
    {:"911"=>
      {"first_name"=>"Phteven",
       "last_name"=>"Cartwright",
       "phone_number"=>911,
       "level_of_caringness"=>"None"},
     :"666"=>
      {"first_name"=>"Carol",
       "last_name"=>"Smellsbad",
       "phone_number"=>666,
       "level_of_caringness"=>"Hateful"},
     :"134"=>
      {"first_name"=>"Bambam",
       "last_name"=>"Idontwanttomaketheseanymore",
       "phone_number"=>134,
       "level_of_caringness"=>"QWERQWER"}}
    

    使用外部迭代器:

    require 'pp'
    
    data = [
      ['first_name', 'last_name', 'phone_number', 'level_of_caringness'],
      ['Phteven', 'Cartwright', 911, 'None'],
      ['Carol', 'Smellsbad', 666, 'Hateful'],
      ['Bambam', 'Idontwanttomaketheseanymore', 134, 'QWERQWER']
    ]
    
    result = {}
    keys = data[0].each
    
    data[1..-1].each do |row|
      values = row.each
      inner_hash = {}
    
      loop do
        inner_hash[keys.next] = values.next
      end
    
      result[row[2].to_s.to_sym] = inner_hash
      keys.rewind
    end
    
    pp result
    
    --output:--
    {:"911"=>
      {"first_name"=>"Phteven",
       "last_name"=>"Cartwright",
       "phone_number"=>911,
       "level_of_caringness"=>"None"},
     :"666"=>
      {"first_name"=>"Carol",
       "last_name"=>"Smellsbad",
       "phone_number"=>666,
       "level_of_caringness"=>"Hateful"},
     :"134"=>
      {"first_name"=>"Bambam",
       "last_name"=>"Idontwanttomaketheseanymore",
       "phone_number"=>134,
       "level_of_caringness"=>"QWERQWER"}}
    

    【讨论】:

      【解决方案2】:
      arr = [
        ['first_name', 'last_name', 'phone_number', 'level_of_caringness'],
        ['Phteven', 'Cartwright', 911, 'None'],
        ['Carol', 'Smellsbad', 666, 'Hateful'],
        ['Bambam', 'Idontwanttomaketheseanymore', 134, 'QWERQWER']
      ]
      
      [arr.first].product(arr[1..-1]).
           map { |keys, values| keys.zip(values).to_h }.
           each_with_object({}) { |g,h| h.update(g["phone_number"]=>g) } 
        #=> [{911=>{"first_name"=>"Phteven", "last_name"=>"Cartwright",
        #           "phone_number"=>911, "level_of_caringness"=>"None"}},
        #    {666=>{"first_name"=>"Carol", "last_name"=>"Smellsbad",
        #          "phone_number"=>666, "level_of_caringness"=>"Hateful"}}, 
        #    {134=>{"first_name"=>"Bambam", "last_name"=>"Idontwanttomaketheseanymore",
        #           "phone_number"=>134, "level_of_caringness"=>"QWERQWER"}}] 
      

      Array#to_h 随 Ruby v.2.0 一起提供,因此如果您使用的是早期版本,请在块中使用 Hash[keys.zip(values)]

      步骤:

      a = [arr.first].product(arr[1..-1])
        #=> [[["first_name", "last_name", "phone_number", "level_of_caringness"],
        #     ["Phteven", "Cartwright", 911, "None"]],
        #    [["first_name", "last_name", "phone_number", "level_of_caringness"],
        #     ["Carol", "Smellsbad", 666, "Hateful"]],
        #    [["first_name", "last_name", "phone_number", "level_of_caringness"],
        #     ["Bambam", "Idontwanttomaketheseanymore", 134, "QWERQWER"]]]
      
      b = a.map { |keys, values| keys.zip(values).to_h }
        #=> [{"first_name"=>"Phteven", "last_name"=>"Cartwright",
        #     "phone_number"=>911, "level_of_caringness"=>"None"},
        #    {"first_name"=>"Carol", "last_name"=>"Smellsbad",
        #     "phone_number"=>666, "level_of_caringness"=>"Hateful"},
        #    {"first_name"=>"Bambam", "last_name"=>"Idontwanttomaketheseanymore",
        #     "phone_number"=>134, "level_of_caringness"=>"QWERQWER"}] 
      

      a第一个值传递给map的块计算如下:

      keys, values = [["first_name", "last_name", "phone_number", "level_of_caringness"],
                      ["Phteven", "Cartwright", 911, "None"]]
        #=> [["first_name", "last_name", "phone_number", "level_of_caringness"],
        #    ["Phteven", "Cartwright", 911, "None"]] 
      keys
        #=> ["first_name", "last_name", "phone_number", "level_of_caringness"] 
      values
        #=> ["Phteven", "Cartwright", 911, "None"] 
      c = keys.zip(values)
        #=> [["first_name", "Phteven"], ["last_name", "Cartwright"],
        #    ["phone_number", 911], ["level_of_caringness", "None"]] 
      c.to_h
        #=> {"first_name"=>"Phteven", "last_name"=>"Cartwright",
        #    "phone_number"=>911, "level_of_caringness"=>"None"} 
      

      最后一步只是将哈希数组转换为前面显示的哈希:

      b.each_with_object({}) { |g,h| h.update(g["phone_number"]=>g) } 
      

      【讨论】:

        【解决方案3】:

        这是一个易于阅读和理解的解决方案。

        def array_to_hash(list)
          result = {}
          keys = list.shift.map(&:to_sym)
          list.each{ |ar| result[ar[2]] = Hash[keys.zip(ar)]}
          result
        end
        

        【讨论】:

          【解决方案4】:

          假设你有一个变量master_list中的数据:

          master_list[1..-1].each_with_object({}) do |arr, m|
            m[arr[2]] = Hash[master_list[0].map(&:to_sym).zip(arr)]
          end
          
          => {911=>
               {:first_name=>"Phteven",
                :last_name=>"Cartwright",
                :phone_number=>911,
                :level_of_caringness=>"None"},
              666=>
               {:first_name=>"Carol",
                :last_name=>"Smellsbad",
                :phone_number=>666,
                :level_of_caringness=>"Hateful"},
              134=>
               {:first_name=>"Bambam",
                :last_name=>"Idontwanttomaketheseanymore",
                :phone_number=>134,
                :level_of_caringness=>"QWERQWER"}}
          

          【讨论】:

          • @CarySwoveland 谢谢。我根据你的cmets更改了解决方案。
          猜你喜欢
          • 1970-01-01
          • 2015-08-12
          • 1970-01-01
          • 1970-01-01
          • 2013-11-13
          • 1970-01-01
          • 2016-09-14
          • 2017-11-22
          • 2020-12-22
          相关资源
          最近更新 更多