[Ruby] CSV ファイルを YAML ファイルへ変換する

フィールド数が分からなかったり、idが行頭にないファイルを、扱いやすい形に整える。

フィールド数が分からないファイルを変換する

いろいろ悩んでいて、こちらで解決させて頂きました。

score.csv
name,score,id
yamada,32,1
suzuki,83,55
tokoro,63,14

“`ruby:csv2yaml.rb
require ‘csv’
require ‘yaml’
require ‘pp’
path_to_csv = ‘score.csv’
path_to_yaml = ‘score.yaml’
csv = CSV.read(path_to_csv, :headers => true).map(&:to_hash)
hash = csv
File.open(path_to_yaml, ‘w’) { |f| f.write(hash.to_yaml) }
pp YAML.load_file(path_to_yaml)

こんな形式にまとまりました。
```yaml:score.yaml
---
- name: yamada
  score: '32'
  id: '1'
- name: suzuki
  score: '83'
  id: '55'
- name: tokoro
  score: '63'
  id: '14'

CSV

:headers オプションで、CSV ファイルの一行目をヘッダとして扱ってくれる。

headers=>false
[["name", "score", "id"],
 ["yamada", "32", "1"],
 ["suzuki", "83", "55"],
 ["tokoro", "63", "14"]]

“`ruby:headers=>true

[[[“name”, “yamada”], [“score”, “32”], [“id”, “1”]],
[[“name”, “suzuki”], [“score”, “83”], [“id”, “55”]],
[[“name”, “tokoro”], [“score”, “63”], [“id”, “14”]]]

> * [class CSV](http://docs.ruby-lang.org/ja/2.1.0/class/CSV.html#I_HEADERS)
### YAML
`to_yaml` メソッドで、hash を YAML ファイルとして保存する。
`.load_file` で、指定した YAML ファイルを読み込み、Ruby オブジェクトを返す。
> * [singleton method YAML.load_file](http://docs.ruby-lang.org/ja/1.8.7/method/YAML/s/load_file.html)
> * [ruby on rails - How do I write values parsed from a CSV file to a YAML file? - Stack Overflow](http://stackoverflow.com/questions/14496674/how-do-i-write-values-parsed-from-a-csv-file-to-a-yaml-file)
YAML フォーマット
> * [第6回 YAMLファイルの扱い方 - WebデザイナーのためのRuby on Rails - Ruby on Rails with OIAX](http://www.oiax.jp/rails/for_web_designers/yaml.html)
> * [Rubyist Magazine - プログラマーのための YAML 入門 (初級編)](http://magazine.rubyist.net/?0009-YAML)
### .map(&:to_hash)
> mapメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。
>
> [map, map! (Array) - Rubyリファレンス](http://ref.xaio.jp/ruby/classes/array/map)
`&:to_hash` は、こういうこと。
```ruby
.map { |item| item.to_hash }

フィールドに含まれている id を活用する

データには、どうやら id が含まれているようなので、これを利用できるようにしたい。

score.csv
name,score,id
yamada,32,1
suzuki,83,55
tokoro,63,14

“`ruby:csv2yaml.rb
require ‘csv’
require ‘yaml’
require ‘pp’
path_to_csv = ‘score.csv’
path_to_yaml = ‘score.yaml’
csv = CSV.read(path_to_csv, :headers => true).map(&:to_hash)
hash = {}
csv.each do |row|
id = row[‘id’].to_i
hash[id] = row
end
File.open(path_to_yaml, ‘w’) { |f| f.write(hash.to_yaml) }
pp yaml = YAML.load_file(path_to_yaml)
pp yaml[55][‘name’]

こんな形式にまとまりました。
```yaml:score.yaml
---
1:
  name: yamada
  score: '32'
  id: '1'
55:
  name: suzuki
  score: '83'
  id: '55'
14:
  name: tokoro
  score: '63'
  id: '14'

こうしておくと、yaml[55]['name']"suzuki" と直感的に取得できるので良さそう。

補遺

Rubyでヘッダ付きのCSVを生成する | deadwood