Posted at

Ruby Array of HashをCSVに変換

More than 3 years have passed since last update.

以下のように順番も必須項目もばらばらのハッシュ配列をCSVに変換したい.

[

{ name: "Newton", age: 84, from: "England", gender: "male" },
{ name: "Planck", age: 89, role: "physicist" },
{ from: "Russia", age: 53, name: "Tchaikovsky", role: "composer" },
{ from: "Czech", name: "Nedved", tel: "00-0000-0000", role: "soccer player" },
]

想定の変換CSV

name,age,from,gender,role,tel

Newton,84,England,male,,
Planck,89,,,physicist,
Tchaikovsky,53,Russia,,composer,
Nedved,,Czech,,soccer player,00-0000-0000

ざっと探したところ標準の方法はないみたいだったので作った.

def hash_list_to_csv_array( list, key_order=nil )

key_order ||= list.map(&:keys).flatten.uniq
arr = list.map do |hash|
key_order.map{|key| hash[key]}
end
arr.unshift(key_order)
end

require "csv"
list = [
{ name: "Newton", age: 84, from: "England", gender: "male" },
{ name: "Planck", age: 89, role: "physicist" },
{ from: "Russia", age: 53, name: "Tchaikovsky", role: "composer" },
{ from: "Czech", name: "Nedved", tel: "00-0000-0000", role: "soccer player" },
]
puts hash_list_to_csv_array( list ).map(&:to_csv).join
# name,age,from,gender,role,tel
# Newton,84,England,male,,
# Planck,89,,,physicist,
# Tchaikovsky,53,Russia,,composer,
# Nedved,,Czech,,soccer player,00-0000-0000

# キーの並びと項目を明示指定したいときは第2引数に指定
puts hash_list_to_csv_array( list, [:role,:name] ).map(&:to_csv).join
# role,name
# ,Newton
# physicist,Planck
# composer,Tchaikovsky
# soccer player,Nedved


Environment

% ruby -v

ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]