[英]can't figure out array of hashes ruby
I am trying to turn an array of arrays into an array of hashes. 我正在尝试将数组数组转换为哈希数组。 Could someone try to explain what I am exactly doing wrong here? 有人可以在这里解释我到底在做什么错吗? The first array within the array of arrays becomes the keys for the hash. 数组数组中的第一个数组成为哈希键。 I can get the method to return one hash or even three of the same hashes. 我可以获得返回一个哈希值甚至三个相同哈希值的方法。 But I can't get it return each different new hash within the final array. 但是我不能让它在最终数组中返回每个不同的新哈希。
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" }
Pair up keys (in table_data[0]
and values (each other row in table_data
) using zip
, and map them to a hash: 使用zip
将键(在table_data[0]
和值(在table_data
每一行) table_data
,并将它们映射到哈希:
table_data[1..-1].map { |values| Hash[table_data[0].zip(values)] }
EDIT: The part that doesn't work in your case is having one single hash that you keep reusing. 编辑:在您的情况下不起作用的部分是您一直重复使用一个哈希。 When you do final_array << hash
, it doesn't add a snapshot of the hash as it is then; 当您执行final_array << hash
,它不会像这样添加哈希的快照; it adds a reference to it. 它添加了对它的引用 。 Thus, you don't have an array of three hashes, you have an array with three references to the same hash. 因此,您没有包含三个散列的数组,而是具有包含对同一哈希的三个引用的数组。 You could avoid it by doing final_array << hash.clone
to actually take a snapshot; 您可以通过执行final_array << hash.clone
来实际拍摄快照来避免这种情况。 or (much simpler) just make a new hash in each iteration of the loop (move hash = {}
into the table_array.each_index
loop). 或(简单得多),只需在循环的每次迭代中创建一个新的哈希(将hash = {}
移动到table_array.each_index
循环中)。
As @Amadan has diagnosed your problem, I will suggest a more "Ruby-like" approach. 由于@Amadan已诊断出您的问题,因此我建议使用一种更“类似于Ruby”的方法。
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"}
# ]
The steps are as follows. 步骤如下。
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"]
# ]
# ]
The first element of a
is passed to map
, the block variable pair
is assigned and the block calculation is performed. 将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"}
Therefore, a.first
is mapped to g
. 因此, a.first
映射到g
。 The remaining calculations are similar. 其余计算类似。
Your question has been properly answered by @CarySwoveland and @Amadan. @CarySwoveland和@Amadan已正确回答了您的问题。
I'd just like to add that your table basically looks like a CSV table with header. 我只想补充一点,您的表基本上看起来像是带标题的CSV表。
If your table_data
does come from a file, you might as well read it directly with 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
It outputs 输出
#<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">
You can work CSV::Row
as with an Hash. 您可以将CSV::Row
与哈希一起使用。 If you really want a Hash, you can use row.to_h
: 如果您确实需要哈希,则可以使用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"}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.