代码之家  ›  专栏  ›  技术社区  ›  Goku

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

  •  0
  • Goku  · 技术社区  · 6 年前

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

    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”开头的行进行了字符串验证,并将服务器名称值推送到一个新数组中,从而每次迭代只打印唯一的值,但没有任何效果。在这里设置标志有什么帮助吗?

    我并没有得到一个逻辑,如何只打印一次服务器和名称值,就像我上面提到的那样。(应为节)

    另外,棘手的问题是为每个“name”部分留一个空白行,比如在olaus51和olaus10之间留一个空白行,对于其他名称值也是如此。 在每个服务器值之间-新的\u-dof1 \u-new和新的\u-dof2 \u-new。

    任何帮助解决这个问题都会很有帮助,谢谢!!

    1 回复  |  直到 6 年前
        1
  •  1
  •   Leo    6 年前

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

    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