How do you convert an array of hashes to a .csv file?
I have tried
CSV.open("data.csv", "wb") do |csv|
@data.to_csv
end
but it is blank
How do you convert an array of hashes to a .csv file?
I have tried
CSV.open("data.csv", "wb") do |csv|
@data.to_csv
end
but it is blank
Try this:
CSV.open("data.csv", "wb") do |csv|
@data.each do |hash|
csv << hash.values
end
end
If you want the first line of the CSV to contain the keys of the hash (a header row), simply do:
CSV.open("data.csv", "wb") do |csv|
csv << @data.first.keys # adds the attributes name on the first line
@data.each do |hash|
csv << hash.values
end
end
Please read the comment of @cgenco below: He wrote a monkey patch for the Array class.
CSV
is smart enough to deal with the non-uniform hashes for you. See the code for CSV::Writer#<<
So, this works, and is a bit simpler than the above examples:
CSV.open("data.csv", "wb", {headers: @data.first.keys} ) do |csv|
@data.each do |hash|
csv << hash
end
end
If the keys are not the same in all rows, the current answers fail. This is the safest approach:
data = [{a: 1, b: 2}, {b: 3, c: 4}]
CSV.open("data.csv", "w") { |csv|
headers = data.flat_map(&:keys).uniq
csv << headers
data.each { |row|
csv << row.values_at(*headers)
}
}
All keys will be present in the CSV, even if they don't appear in the first row:
a | b | c |
---|---|---|
1 | 2 | |
3 | 4 |
If the hashes aren't uniform then you will end up with data in the wrong columns. You should use values_at instead:
CSV.open("data.csv", "wb") do |csv|
keys = @data.first.keys
csv << keys
@data.each do |hash|
csv << hash.values_at(*keys)
end
end
None of the other answers worked for me for one reason or another, so I'll throw in my contribution as well. Here's what worked for me for my array of hashes with ruby 2.7:
headers = data.map(&:keys).flatten.uniq
CSV.open("data.csv", "wb", {headers: headers} ) do |csv|
csv << headers
data.each do |hash|
csv << hash
end
end