如何在Ruby中的哈希循环数组中设置标志

时间:2018-07-16 04:50:29

标签: ruby-on-rails ruby

我已经处理了一个输入文件并创建了以下格式的数据结构

final = [ {:server=>"new_US_dof1_new"},
{:name=>"OLAUS51", :data=>{"HAL"=>"6.93817139", "CCN_RESP"=>".035400391", "PA_RESP"=>".032287598", "PE_RESP"=>".000610352"}},
{:name=>"OLAUS10", :data=>{"HAL"=>"52.7266846", "CFG_RESP"=>"15.9489746"}},
{:name=>"IdofQA03", :data=>{"PA_RESP"=>".096374512"}},
{:name=>"QEMDB", :data=>{"HAL"=>"22.2698975", "PA_RESP"=>"11.7857666", "CCN_RESP"=>".229125977", "PE_RESP"=>".007202148"}},
{:name=>"OLAUS64", :data=>{"CCN_RESP"=>".757202148"}},
{:name=>"IISCR70", :data=>{}},
{:name=>"IQDV500", :data=>{}},
{:name=>"OLAUS80", :data=>{"PA_RESP"=>"10.5393066", "HAL"=>"4.73620605", "CCN_RESP"=>".023864746", "PE_RESP"=>".003723145", "OPENREPORTS"=>".001708984", "REPORT_RESP"=>".001281738"}},

{:server=>"new_US_dof2_new"},
{:name=>"IBDVHAL", :data=>{"HAL"=>"1.81048584", "FM_RESP"=>".001098633"}},
{:name=>"DEVSITEP", :data=>{"HAL"=>".088012695", "PE_RESP"=>".000610352"}},
{:name=>"OLAUS87", :data=>{"CFG_RESP"=>"1.57061768", "HAL"=>".47253418", "PA_RESP"=>".011962891", "PE_RESP"=>".007202148"}}]

我想出了以下代码来处理并获得上述格式

final = []
count = -1

output = File.open("input.txt").read
output.each_line do |line|
  line.strip!
  next if line.empty?
  next if line.include?('rows') || line.include?('occ')
  next if ['-','='].include? line[0]
  parts = line.split ' '
   if parts.size == 1 and line.start_with?('new_')
    final[count += 1] = {server: line, data: {}}
    next
  elsif parts.size == 1 and parts = /^(?!.*new_).*$/
    final[count += 1] = {name: line, data: {}}
    next
  end

  parts.each_cons(2) do |key, value|
    final[count][:data][key] = value 
    end
end

p = Axlsx::Package.new
p.workbook.add_worksheet(:name => "Basic") do |sheet|

    style1 = sheet.styles.add_style(:bg_color => "EF0920", :fg_color => "FFFFFF", b:true, :sz => 14, :alignment => { :horizontal=> :center })
    style2 = sheet.styles.add_style(:bg_color => "00FF00", :fg_color => "FFFFFF", b:true, :sz => 12, :alignment => { :horizontal=> :center })
    sheet.add_row ["VM", "NAME", "DATA", "SIZE"], :style => style1

    final.each do |val|
     if val.key?(:server) 
       sheet.add_row [ val[:server], val[:name], "", "" ] , :style =>[style2, nil]
       next
    elsif val.key?(:name)
      sheet.add_row [ "", val[:name], "", "" ]
      val[:data].each do |k, v|
        sheet << ["", "", k, v]
          end       
       end
    end 
end

我正在尝试将数据格式化为以下结构(预期

enter image description here

但是我的代码抛出类似这样的输出

enter image description here

因此,我将打印值修改为

val[:data].each do |k, v|
        sheet << [val[:server], val[:name], k, v]
    end 

但是在每行打印服务器和名称值 enter image description here

我使用if循环进行了字符串验证,以匹配以'new_'开头的行,并将服务器和名称值推送到新数组,从而在每次迭代中仅打印唯一值,但没有任何效果。在这里设置标志会有所帮助吗?

我并没有完全知道如何打印服务器和命名值的逻辑,就像我上面提到的那样。 (预期部分)

此外,棘手的事情是在每个“名称”部分保留一个空白行-就像OLAUS51和OLAUS10之间的空行一样,其他名称值也是如此 在每个服务器值之间-new_US_dof1_new和new_US_dof2_new。

任何帮助解决此问题的方法都将大有帮助,非常感谢!

1 个答案:

答案 0 :(得分:1)

为什么不呢?根据我过去的回答:

final.each_with_object([]) do |val, line|
  # when key :server exist set server's name as first element for line
  # otherwise set empty value to create a blank cell at position 1
  line << (val.key?(:server) ? val[:server] : '') if line.empty?

  # when key :server exist, in the current hash no needed data
  next if val.key?(:server)

  # at this place line look like [server_name/'']
  # so, when no key :server, in each base hash present keys :name and :data
  line << val[:name]

  # line => [server_name, name] for new server
  # line => ['', name] for new properties for the same server

  # for {name: 'some name', data: {}}
  sheet.add_row [*line, '', ''], :style =>[style2, nil] if val[:data].empty?

  val[:data].each do |k, v|
    # add values from data hash
    line << k << v

    # push line to the sheet
    # first iteration for val[:data]
    # line => [server_name/'', name, data_key, data_value]
    # iteration 2+
    # line => ['', '', data_key, data_value]
    sheet.add_row line.clone, :style =>[style2, nil]

    # array line from each_with_object can't be replaced but can be cleaned
    line.clear

    # line => []
    # push two blank values
    line << '' << ''
    # line => ['', '']
    # that line's data will be used for the current loop
  end

  # add a blank line after block :data
  sheet.add_row []

  # line => ['', '']
  # cleaning a line for next hash
  line.clear
  # line => []
end