[Ruby] CSV ファイルを YAML ファイルへ変換する
フィールド数が分からなかったり、idが行頭にないファイルを、扱いやすい形に整える。
Contents
フィールド数が分からないファイルを変換する
いろいろ悩んでいて、こちらで解決させて頂きました。
こんなデータがあるとして
name,score,id
yamada,32,1
suzuki,83,55
tokoro,63,14
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)
こんな形式にまとまりました。
---
- name: yamada
score: '32'
id: '1'
- name: suzuki
score: '83'
id: '55'
- name: tokoro
score: '63'
id: '14'
CSV
:headers
オプションで、CSV ファイルの一行目をヘッダとして扱ってくれる。
[["name", "score", "id"],
["yamada", "32", "1"],
["suzuki", "83", "55"],
["tokoro", "63", "14"]]
#<csv::Table mode:col_or_row row_count:4>
[[["name", "yamada"], ["score", "32"], ["id", "1"]],
[["name", "suzuki"], ["score", "83"], ["id", "55"]],
[["name", "tokoro"], ["score", "63"], ["id", "14"]]]
YAML
to_yaml
メソッドで、hash を YAML ファイルとして保存する。
.load_file
で、指定した YAML ファイルを読み込み、Ruby オブジェクトを返す。
YAML フォーマット
.map(&:to_hash)
mapメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。
&:to_hash
は、こういうこと。
.map { |item| item.to_hash }
フィールドに含まれている id を活用する
データには、どうやら id が含まれているようなので、これを利用できるようにしたい。
name,score,id
yamada,32,1
suzuki,83,55
tokoro,63,14
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']
こんな形式にまとまりました。
---
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"
と直感的に取得できるので良さそう。