将哈希转换为csv文件

时间:2013-03-09 23:06:29

标签: ruby csv

我有以下名为fcs的哈希,并希望将其保存为CSV。

{
  "bla"=>{
          "lower"=>[17.12241, 18.79847, 17.71413, 18.49174, 18.30381, 18.78557, 18.93176, 19.33453, 19.62619, 20.02301],
          "point"=>[21.84838, 23.86319, 23.93176, 25.19658, 25.72613, 26.70761, 27.41132, 28.28576, 29.05525, 29.88925],
          "upper"=>[26.57434, 28.92791, 30.14938, 31.90142, 33.14845, 34.62966, 35.89088, 37.23698, 38.48432, 39.7555]
         },
  "blo"=>{
          "lower"=>[17.12241, 18.79847, 17.71413, 18.49174, 18.30381, 18.78557, 18.93176, 19.33453, 19.62619, 20.02301],
          "point"=>[21.84838, 23.86319, 23.93176, 25.19658, 25.72613, 26.70761, 27.41132, 28.28576, 29.05525, 29.88925],
          "upper"=>[26.57434, 28.92791, 30.14938, 31.90142, 33.14845, 34.62966, 35.89088, 37.23698, 38.48432, 39.7555]
         }
}

这是输出文件的所需内容:

lower.bla,bla,upper.bla,lower.blo,blo,upper.blo
17.12241,21.84838,26.57434,17.12241,21.84838,26.57434
18.79847,23.86319,28.92791,18.79847,23.86319,28.92791
.
.
.

我使用以下代码生成它:

def to_csv
  fcs = self.fcs
  CSV.generate(col_sep: self.delim) do |csv|
    names = Array.new
    cols = Array.new
    fcs.keys.each do |ts|
      names << "lower." + ts
      names << ts
      names << "upper." + ts
    end
    csv << names
    fcs.values.each do |ts|
      cols << ts.values       
    end
    cols.flatten(1).transpose.each do |row|
      csv << row
    end
  end
end

然而,它使用三个不同的循环。我觉得这不是实现所需输出的最佳代码。有没有最好的方法来重写它?

1 个答案:

答案 0 :(得分:1)

header, body =
fcs
.flat_map{|k1, h| h.map{|k2, v| ["#{k2}.#{k1}".sub(/point\./, ""), v]}}
.transpose

[header, *body.transpose].map{|e| e.join(",")}.join($/)

给出:

lower.bla,bla,upper.bla,lower.blo,blo,upper.blo
17.12241,21.84838,26.57434,17.12241,21.84838,26.57434
18.79847,23.86319,28.92791,18.79847,23.86319,28.92791
17.71413,23.93176,30.14938,17.71413,23.93176,30.14938
18.49174,25.19658,31.90142,18.49174,25.19658,31.90142
18.30381,25.72613,33.14845,18.30381,25.72613,33.14845
18.78557,26.70761,34.62966,18.78557,26.70761,34.62966
18.93176,27.41132,35.89088,18.93176,27.41132,35.89088
19.33453,28.28576,37.23698,19.33453,28.28576,37.23698
19.62619,29.05525,38.48432,19.62619,29.05525,38.48432
20.02301,29.88925,39.7555,20.02301,29.88925,39.7555