简体   繁体   English

无法找出哈希红宝石数组

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM