[Ruby] CSV ファイルを YAML ファイルへ変換する
フィールド数が分からなかったり、idが行頭にないファイルを、扱いやすい形に整える。
[markdown]
## フィールド数が分からないファイルを変換する
いろいろ悩んでいて、こちらで解決させて頂きました。
> * [A Quick Path from CSV to YAML](http://commandercoriander.net/blog/2013/06/22/a-quick-path-from-csv-to-yaml/)
こんなデータがあるとして
“`csv: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 ファイルの一行目をヘッダとして扱ってくれる。
“`ruby: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 }
“`
> * [Rubyで .map(&:first) と .map{|e| e.first } が同じになる理由は?【解決編】 – YNote](http://d.hatena.ne.jp/yoshidaa/20110515/1305431262)
> * [RubyのSymbol#to_procを考えた人になってみる](http://melborne.github.io/2008/09/17/Ruby-Symbol-to_proc/)
> * [[初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか – Qiita](http://qiita.com/jnchito/items/dedb3b889ab226933ccf)
> * [Rubyのmap(&:name)というのはどういう意味? – QA@IT](http://qa.atmarkit.co.jp/q/35)
## フィールドに含まれている id を活用する
データには、どうやら id が含まれているようなので、これを利用できるようにしたい。
“`csv: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](https://www.d-wood.com/blog/2015/11/14_7685.html)
[/markdown]