概要
CSV.parseに、headers: trueを渡した時とそうでないときでのデータ構造の違いを比較
headers: trueありの場合でしか使ったことがなかったので、このオプションがある場合とない場合で比較してみました。
rails consoleとrspecのfixture_file_upload
を使って確認しています。
cryptocurrency.csv
number,name,symbol
1,Bitcoin,BTC
2,XRP,XRP
3,Quant,QNT
headers: trueなし
pry(main)> filepath = "/path/to/cryptocurrency.csv"
pry(main)> data = fixture_file_upload(filepath, "text/csv")
pry(main)> str = data.read
=> "number,name,symbol\n1,Bitcoin,BTC\n2,XRP,XRP\n3,Quant,QNT\n"
# 配列を要素に持つ配列で返ってくる
pry(main)> csv = CSV.parse(str)
=> [["number", "name", "symbol"], ["1", "Bitcoin", "BTC"], ["2", "XRP", "XRP"], ["3", "Quant", "QNT"]]
pry(main)> csv.class
=> Array
pry(main)> csv.count
=> 4
headers: trueあり
pry(main)> csv = CSV.parse(str, headers: true)
=> #<CSV::Table mode:col_or_row row_count:4>
pry(main)> csv.class
=> CSV::Table
pry(main)> csv[0].class
=> CSV::Row
# row_countが4だけど、csv.countが3は何でだろうと思ったけど、csv.countはデータ行のカウントだけを返すのだと理解
pry(main)> csv.count
=> 3
pry(main)> csv.headers
=> ["number", "name", "symbol"]
# to_aで、CSV.parse(str)と同じ結果が返ってくる
pry(main)> csv.to_a
=> [["number", "name", "symbol"], ["1", "Bitcoin", "BTC"], ["2", "XRP", "XRP"], ["3", "Quant", "QNT"]]
pry(main)> csv[0]
=> #<CSV::Row "number":"1" "name":"Bitcoin" "symbol":"BTC">
pry(main)> csv[1]
=> #<CSV::Row "number":"2" "name":"XRP" "symbol":"XRP">
pry(main)> csv[2]
=> #<CSV::Row "number":"3" "name":"Quant" "symbol":"QNT">
pry(main)> csv[3]
=> nil
pry(main)> csv.each do |row|
pry(main)* p row
pry(main)* end
#<CSV::Row "number":"1" "name":"Bitcoin" "symbol":"BTC">
#<CSV::Row "number":"2" "name":"XRP" "symbol":"XRP">
#<CSV::Row "number":"3" "name":"Quant" "symbol":"QNT">
headers: trueなしの場合は、CSVの各行が配列になって、それらが全て配列に入っているみたい。
headers: trueありの場合は、CSVの先頭行はヘッダー扱いで、データ行は、CSV::ROWというオブジェクトになって
<CSV::Row "number":"1" "name":"Bitcoin" "symbol":"BTC">
のようなHashとなり、ヘッダーがKeyになるみたいだということが改めて分かりました。
row_countが4だけど、csv.countが3が一番もやっとしました。
row_countが4だから、csv[0]で、ヘッダーが返ってくるかと思ったら、そうでないし。
分かりにくなあと個人的に思いました。