LoginSignup
93
79

More than 5 years have passed since last update.

【Ruby】よく使う、CSVライブラリを使ったCSV操作

Last updated at Posted at 2016-10-16

Ruby標準ライブラリのcsvを使ったCSV操作で、個人的によく使うものを整理した。

次のfuture_gadgets.csvという名称のCSVファイルを例として使う。

future_gadgets.csv
number,name,function
1号機,ビット粒子砲,おもちゃの光線銃にテレビのリモコンを合体させたもの
2号機,タケコプカメラー,軸の部分に小型カメラを仕込んだ竹トンボ
3号機,もしかしてオラオラですかーっ!?,ウソ発見器と称した発汗検知装置

出典: https://ja.wikipedia.org/wiki/STEINS;GATEの用語一覧

CSVファイルから1行ずつ読み取りたい

CSV#foreachを使う。
1行は1つの配列として表現される。

require 'csv'

CSV.foreach('/path/to/future_gadgets.csv') do |fg|
  # fgはArrayクラス
  puts "[#{fg[0]}] #{fg[1]}: #{fg[2]}"
end

1行ずつ処理をするため、行数が多いCSVファイルを扱う場合でもメモリ使用量を気にしないで使える。

実行結果
[number] name: function
[1号機] ビット粒子砲: おもちゃの光線銃にテレビのリモコンを合体させたもの
[2号機] タケコプカメラー: 軸の部分に小型カメラを仕込んだ竹トンボ
[3号機] もしかしてオラオラですかーっ!?: ウソ発見器と称した発汗検知装置

CSVファイルから1度に読み込みたい

CSV#readを使う。
1行は1つの配列として表現され、全体として配列の配列が返り値となる。

require 'csv'

future_gadgets = CSV.read('/path/to/future_gadgets.csv')
future_gadgets.each do |fg|
  # fgはArrayクラス
  puts "[#{fg[0]}] #{fg[1]}: #{fg[2]}"
end
実行結果
[number] name: function
[1号機] ビット粒子砲: おもちゃの光線銃にテレビのリモコンを合体させたもの
[2号機] タケコプカメラー: 軸の部分に小型カメラを仕込んだ竹トンボ
[3号機] もしかしてオラオラですかーっ!?: ウソ発見器と称した発汗検知装置

CSV文字列から読み取りたい

ファイルではなく文字列としてのCSVを受け取りたい場合は、CSV#parseを使う。
CSV#foreachと同じく、ブロックには行が配列として渡される。

require 'csv'

CSV.parse('foo,bar,baz') do |fg|
  puts fg[0] # => 'foo'
  puts fg[1] # => 'bar'
  puts fg[2] # => 'baz'
end

ヘッダのフィールド名をキーにして操作したい

CSV.foreachCSV.parseの第2引数にはHash形式でオプションを渡すことができ、ここにheaders: trueを与えることで、先頭行をヘッダして読み取ってくれるようになる。

これにより、ブロックに渡されるオブジェクトのクラスがArrayからCSV::Rowになる。
CSV::Rowはフィールド名をキーとして使えるようになるのでコードが読みやすくなる。

require 'csv'

CSV.foreach('/path/to/future_gadgets.csv', headers: true) do |fg|
  # fgはCSV::Row
  puts "[#{fg['number']}] #{fg['name']}: #{fg['function']}"
end
実行結果
[1号機] ビット粒子砲: おもちゃの光線銃にテレビのリモコンを合体させたもの
[2号機] タケコプカメラー: 軸の部分に小型カメラを仕込んだ竹トンボ
[3号機] もしかしてオラオラですかーっ!?: ウソ発見器と称した発汗検知装置

空行を読み飛ばしたい

skip_blanks: trueをオプションとして渡す。
指定しない場合空行は空の配列などになるが、このオプションを指定することでスキップできる。

require 'csv'

CSV.foreach('/path/to/future_gadgets.csv', skip_blanks: true) do |fg|
  # ...
end

空行があるとエラーになってしまったり面倒なチェック処理が必要になる場合が多いので、とりあえず指定することが多い。

TSVを読み取りたい

RubyのCSVライブラリは、名前からCSVしか操作できないような印象を受けるがそうではない。
col_sepオプションで区切り文字を自由に設定できるので、TSVでも同じように扱うことができる。

require 'csv'

CSV.foreach('/path/to/future_gadgets.tsv', col_sep: "\t") do |fg|
  # ...
end
93
79
0

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
93
79