複数のcsvファイルからなにやら取ってきて、変換したり書き出したりするものを作っています。
書き出してみると自分でなにやってるか怪しいなぁ。
というオブジェクトを並べて、途中に出力があったりする複雑なプロセスのコンバートをやらせようということです。
#!ruby -KS require 'yaml' require 'csv' # ================ definition MACRO_TABLE = { :TO_I => lambda{|x| x.to_i} , :TIMEONLY => lambda{|x| x.match(/\b(\d{1,2}:\d{1,2}):\d{1,2}$/).to_a[1]} , } # ================ classes class RuledFields attr_accessor :names , :rules, :defaults def initialize @separator = /\t/ @glue = "," @data = nil @data_by_name = {} @names = [] @rules = {} @defaults = {} # names: field order [:id, :name, :category_id] # rules: convert map {:id=>lambda{|x| x.to_i},..} # defaults: defaultv {:id=>0, ...} end # fetch from object def fetch_from obj data_imported = obj.get_record @data_by_name = self.parse(data_imported) end # parsing according to rule def parse(data_hash) # order keys, convert values, insert default rethash = {} @names.each{|aname| value = data_hash[aname] if (value == nil && @defaults[aname]) then value = @defaults[aname] end if(@rules[aname] && value != nil) then value = @rules[aname].call(value) end rethash[aname] = value } return rethash end # set record aline def set_data(data) @data = data self.prepare_record end def prepare_record # re-map to names return unless @data @names.each_with_index{|name, idx| @data_by_name[name] = @data[idx] } end def load_rules (filename) # rf2.names = [:name, :id , :hoge] # rf2.defaults = {:hoge=>'0000'} # rf2.rules = {:name=>lambda{|x| x.upcase}} yaml_fi = open(filename) lines = yaml_fi.readlines.join('') obj = YAML::load(lines) yaml_fi.close obj['fields'].each{|fparam| @names << fparam['fieldname'].to_sym if fparam['default'] @defaults[fparam['fieldname'].to_sym] = fparam['default'] end if fparam['rule'] @rules[fparam['fieldname'].to_sym] = eval(fparam['rule']) end if fparam['macro'] @rules[fparam['fieldname'].to_sym] = MACRO_TABLE[fparam['macro'].to_sym] end } end def get_record @data_by_name end def get_record_by_name names # return fields by name @data_by_name[names] end end
yamlはこんな感じで。
name: companies file: companies_source.txt encoding: utf8 fields: - fieldname: id default: 100 macro: TO_I - fieldname: company_id macro: TO_I - fieldname: group_id macro: TO_I - fieldname: open_time macro: TIMEONLY #....
memo |
30代のおっさんです。未来がないなりに頑張ります。
http://www.ruby-lang.org/ja/man/html/Enumerable.html#inject
って、ありゃ、0から1000だったら、上の例は失敗しますね(順番に10で割ってるけど、0のときはカウントされない)…。すいません。
「1の出現数」「2の出現数」みたいな応用もきかないし、素直に文字列として処理(injectの例みたいに)したほうがいいと思います。
print (0..1000).map{|i|i.to_s}.join.count('0');
とかでも。