はじめに
ホストコンピュータ(死語?)から吐き出されたような超長い固定長ファイルが好物です。嘘です。
1行が数百バイト以上(2500バイトとかのファイルあるからね!)、数十から数百項目のExcelの定義書をもらったら時に、私がいつもやっているやり方です。
準備
固定長ファイルなので、定義書は神Excelです!
まずはExcelからキーと1カラムの長さの列を取得して、ペアを作ります。
column_def.rb
Column_def =%w[
any_id 10
any_field1 2
cyclic_1 4
cyclic_2 4
cyclic_3 4
]
# キーと列長のペア
Columns = Hash[*Column_def]
# => {"any_id"=>"10","any_field1"=>"2","cyclic_1"=>"4","cyclic_2"=>"4","cyclic_3"=>"4"}
# 一行のサンプル
input_sample = "0123456789xx12345678abcd"
分解
column_def.rb
# unpackが有能なのでunpackのパターンを作る
column_def = Columns.values.map{|c| "a#{c}"}.join
#=> "a10a2a4a4a4"
arr = input_sample.unpack(column_def)
#=> ["0123456789", "xx", "1234", "5678", "abcd"]
この通り綺麗に分解してくれます。String#unpack有能。
構築
column_def.rb
# Columnを再利用して、さらに扱いやすく
any_item = Hash[Columns.keys.zip(arr)]
#=> {"any_id"=>"0123456789","any_field1"=>"xx", "cyclic_1"=>"1234", "cyclic_2"=>"5678", "cyclic_3"=>"abcd"}
zipした2重配列を連想配列にしてくれるHash有能。
これならjsonや欲しい形に変換して使いやすい。ですよね?
column_def.rb
require "json"
any_item.to_json
#=> "{\"any_id\":\"0123456789\",\"any_field1\":\"xx\",\"cyclic_1\":\"1234\",\"cyclic_2\":\"5678\",\"cyclic_3\":\"abcd\"}"
まとめ
このやり方でいろんな固定長ファイルをサクッと片付けてください。(もっといいやり方、教えて・・・)
CSVでも連想配列にするところは使えますよ。(CSVのクラスはよく使い方忘れるので、ただのArray、Hashが好き)
固定長ファイルは正規化されていないことが多いから、group_byも有能である事はまた今度書こうかな。
Ruby有能。String#unpack有能。Hash有能。
・・・本当はPythonで同じことをやりたい・・・けどRuby以外書けないのです。