半年に一回ぐらい CSV を読み込む必要に迫られて、その度にリファレンスで CSV 読み込み時のオプションを調べているので、よく使うやつを書いておく。
毎回やりたいこと
例えば以下の様な CSV があったとして、毎回次のようなことをやりたいと思ってリファレンスを調べる。
-
each
でイテレーションするときにヘッダー行は含めたくない - 各行は配列ではなくヘッダー行の各要素をキーにするハッシュっぽく扱いたい
- ハッシュのキーは「名前」や「部署」ではなく
:row
や:department
のようなシンボルにしたい - 数字は文字列ではなく数値として取得したい
- 空白行はスキップしたい
test.csv
ID,名前,部署,入社年度
1,山田太郎,人事部,2000
2,山田花子,経理部,2015
やり方
以下のようにすればできる。
require 'csv'
HEADER_TO_SYM_MAP = {
'ID' => :id,
'名前' => :name,
'部署' => :department,
'入社年度' => :year_joined
}
header_converter = lambda { |h| HEADER_TO_SYM_MAP[h] }
csv = CSV.read('test.csv', headers: :first_row, header_converters: header_converter, converters: :integer, skip_blanks: true)
csv.each do |row|
p row
HEADER_TO_SYM_MAP.values.each { |k| puts "#{k} : #{row[k]}" }
end
こんな結果になる。
#<CSV::Row id:1 name:"山田太郎" department:"人事部" year_joined:2000>
id : 1
name : 山田太郎
department : 人事部
year_joined : 2000
#<CSV::Row id:2 name:"山田花子" department:"経理部" year_joined:2015>
id : 2
name : 山田花子
department : 経理部
year_joined : 2015
オプションの説明
headers
:first_row
を指定しておくと、一行目をヘッダとして扱い、以降の列が配列ではなく、ヘッダ行の各要素をキーとしてハッシュっぽくアクセスできる Row オブジェクトになる。配列を渡せばそれをヘッダー行として扱ってくれる。
converters/header_converters
converters は各行のコンバータを、header_converters はヘッダー行の変換を行うコンバータを指定する。CSV::Converters に書いてあるように、数字の変換などは予め用意されていてシンボルを渡すだけでできる。また、上記の例のように lambda を渡して自分で変換ルールを指定することもできる。
skip_blanks
true なら空行をスキップする
自分が使うのはこれぐらいです。他にも良いやり方があるよ、という方はぜひコメント下さい。