无法弄清楚哈希的哈希数组

时间:2017-01-30 04:31:41

标签: arrays ruby hash nested

我正在尝试将数组数组转换为哈希数组。有人可以尝试解释我在这里做错了什么吗?数组数组中的第一个数组成为哈希的键。我可以让方法返回一个哈希值甚至三个相同的哈希值。但我不能让它返回最终数组中的每个不同的新哈希。

table_data = [
  ["first_name", "last_name", "city", "state"],
  ["Elisabeth", "Gardenar", "Toledo", "OH"],
  ["Jamaal", "Du", "Sylvania", "OH"],
  ["Kathlyn", "Lavoie", "Maumee", "OH"]
]


def convert_table(table_array)
  hash = {}
  final_array = []
  headers_array = table_array.shift

  table_array.each_index do |x|
    i = 0
    until i == headers_array.length
      hash[headers_array[i]] = table_array[x][i]
      final_array << hash
      i += 1
    end
  end
  final_array
end

p convert_table(table_data)

#END GOAL
[ { "first_name" => "Elisabeth", "last_name" => "Gardenar", "city" => "Toledo", "state" => "OH" },
{ "first_name" => "Jamaal", "last_name" => "Du", "city" => "Sylvania", "state"    => "OH" },
{ "first_name" => "Kathlyn", "last_name" => "Lavoie", "city" => "Maumee", "state" => "OH" }

3 个答案:

答案 0 :(得分:2)

使用table_data[0]配对密钥(table_datazip中的每一行),并将它们映射到哈希:

table_data[1..-1].map { |values| Hash[table_data[0].zip(values)] }

编辑:在你的情况下不起作用的部分是有一个你不断重用的哈希。执行final_array << hash时,它不会添加哈希的快照,因为它是;它为它添加了引用。因此,您没有三个哈希的数组,您有一个数组,其中有三个对同一哈希的引用。您可以通过final_array << hash.clone来实际拍摄快照来避免它;或者(更简单)只需在循环的每次迭代中创建一个新哈希(将hash = {}移动到table_array.each_index循环中)。

答案 1 :(得分:1)

@Amadan已经诊断出您的问题,我会建议更多类似Ruby的&#34;方法

keys, *data = table_data
  #=> [["first_name", "last_name", "city", "state"],
  #    ["Elisabeth", "Gardenar", "Toledo", "OH"],
  #    ["Jamaal", "Du", "Sylvania", "OH"],
  #    ["Kathlyn", "Lavoie", "Maumee", "OH"]
  #   ]
keys
  #=> ["first_name", "last_name", "city", "state"] 
data
  #=> [["Elisabeth", "Gardenar", "Toledo", "OH"],
  #    ["Jamaal", "Du", "Sylvania", "OH"],
  #    ["Kathlyn", "Lavoie", "Maumee", "OH"]
  #   ] 

[keys].product(data).map { |pair| pair.transpose.to_h }
  #=> [{"first_name"=>"Elisabeth", "last_name"=>"Gardenar", "city"=>"Toledo", 
  #       "state"=>"OH"},
  #    {"first_name"=>"Jamaal", "last_name"=>"Du", "city"=>"Sylvania",
  #       "state"=>"OH"},
  #    {"first_name"=>"Kathlyn", "last_name"=>"Lavoie", "city"=>"Maumee",
  #       "state"=>"OH"}
  #   ] 

步骤如下。

a = [keys].product(data)
  #=> [[["first_name", "last_name", "city", "state"],
  #     ["Elisabeth", "Gardenar", "Toledo", "OH"]
  #    ],
  #    [["first_name", "last_name", "city", "state"],
  #     ["Jamaal", "Du", "Sylvania", "OH"]],
  #    [["first_name", "last_name", "city", "state"],
  #     ["Kathlyn", "Lavoie", "Maumee", "OH"]
  #    ]
  #   ] 

a的第一个元素传递给map,分配块变量pair并执行块计算。

pair = a.first
  #=> [["first_name", "last_name", "city", "state"],
  #    ["Elisabeth", "Gardenar", "Toledo", "OH"]
  #   ] 
b = pair.transpose
  #=> [["first_name", "Elisabeth"],
  #    ["last_name", "Gardenar"],
  #    ["city", "Toledo"],
  #    ["state", "OH"]
  #   ] 
g = b.to_h
  #=> {"first_name"=>"Elisabeth", "last_name"=>"Gardenar", "city"=>"Toledo",
  #      "state"=>"OH"} 

因此,a.first会映射到g。剩下的计算是类似的。

答案 2 :(得分:0)

@CarySwoveland和@Amadan正确回答了你的问题。

我想补充一点,你的表基本上看起来像带有标题的CSV表。

如果您的table_data确实来自某个文件,您也可以直接使用CSV阅读:

csv_table = "first_name,last_name,city,state
Elisabeth,Gardenar,Toledo,OH
Jamaal,Du,Sylvania,OH
Kathlyn,Lavoie,Maumee,OH"

require 'csv'

CSV.parse(csv_table, headers: true).each do |row|
  p row
end

输出

#<CSV::Row "first_name":"Elisabeth" "last_name":"Gardenar" "city":"Toledo" "state":"OH">
#<CSV::Row "first_name":"Jamaal" "last_name":"Du" "city":"Sylvania" "state":"OH">
#<CSV::Row "first_name":"Kathlyn" "last_name":"Lavoie" "city":"Maumee" "state":"OH">

您可以像使用哈希一样工作CSV::Row。 如果您真的想要哈希,可以使用row.to_h

{"first_name"=>"Elisabeth", "last_name"=>"Gardenar", "city"=>"Toledo", "state"=>"OH"}
{"first_name"=>"Jamaal", "last_name"=>"Du", "city"=>"Sylvania", "state"=>"OH"}
{"first_name"=>"Kathlyn", "last_name"=>"Lavoie", "city"=>"Maumee", "state"=>"OH"}