67
58

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CSV のヘッダー行の日本語をシンボルに変換して要素にアクセスしたりとか

Posted at

半年に一回ぐらい 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 なら空行をスキップする


自分が使うのはこれぐらいです。他にも良いやり方があるよ、という方はぜひコメント下さい。

67
58
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
58

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?