2015-01-13 68 views
0

我有红宝石嵌套散列:转换嵌套在红宝石散列到一个表格式

{"Table1"=>{"Acct type"=>{"Expected"=>"ACC", "Actual"=>"ACC"}, "Seq No"=>{"Expected"=>"100.0", "Actual"=>#<BigDecimal:56d0b28,'0.1E3',9(18)>}, "Class"=>{"Expected"=>"AC", "Actual"=>"AC"}}, "Table 2"=>{"Date"=>{"Expected"=>"20140606", "Actual"=>"20130606"}}} 

我需要显示在表格格式上述嵌套散列 -

Table Field Expected Value Actual Value 
Table 1 Acct type ACC   ACC 
Table 1 Seq No  100.0   100.0 
Table 1 Class  AC    AC 
Table 2 Date  20140606  20130606 

任何建议/指针会非常有帮助。我曾尝试使用'tableprint'和'text-table'宝石,但无法获得理想的效果。上述数据是使用ActiveRecord从DB2表中获取的。

+1

请正确格式化并标记您的问题。你在用什么语言? –

+0

谢谢,更新了我的问题。 – Kiran

+0

你应该检查这个问题。 http://stackoverflow.com/questions/19534040/ruby-1-9-parse-hash-into-an-html-table –

回答

0

这里是一个解决方案:

x = { 
    "Table1"=>{ 
    "Acct type"=>{"Expected"=>"ACC", "Actual"=>"ACC"}, 
    "Seq No"=>{"Expected"=>"100.0", "Actual"=> 100.00}, 
    "Class"=>{"Expected"=>"AC", "Actual"=>"AC"} 
    }, 
    "Table 2"=>{ 
    "Date"=> {"Expected"=>"20140606", 
       "Actual"=>"20130606"}}} 

def table_row(row_name, row_values) 
    [row_name, row_values["Expected"], row_values["Actual"]] 
end 

def table_rows(table_hash) 
    table_hash.map do |field_name, field_values| 
    table_row(field_name, field_values) 
    end 
end 

def widest_string_lengths(visual_table) 
    table_columns_count = visual_table.first.size - 1 
    0.upto(table_columns_count).map do |index| 
    columns = visual_table.map { |row| row[index].to_s } 
    columns.max_by(&:length).length + 2 
    end 
end 

def aligned_visual_table(visual_table) 
    widest_string_items = widest_string_lengths(visual_table) 

    visual_table.map do |row| 
    row.each_with_index.map do |cell, index| 
     cell.to_s.ljust(widest_string_items[index] + 2) 
    end 
    end 
end 

table_headers = ['Table', 'Field', 'Value', 'Actual Value'] 

# This just turns the hash to array of arrays 
visual_table = x.map do |table_name, table_hash| 
    table_rows(table_hash).map do |table_rows| 
     table_rows.insert(0, table_name) 
    end 
end.flatten(1).insert(0, table_headers) 

puts "*********" 
puts aligned_visual_table(visual_table).map(&:join).join("\n") 
+0

真棒!!!!它工作了,谢谢,一吨。 – Kiran

0

你例子表明不存在影响该表的外观未指定的参数。例如,列标签“表”和“字段”是左侧调整的,而“预期值”和“实际值”不是。此外,“期望值”重叠“科目类型”。下面我建议你如何构建表格,但我做了妥协:左侧调整所有列标签,不垂直重叠。

代码

def print_table(h, column_labels_and_spacing, table_label) 
    column_labels = column_labels_and_spacing.map(&:first) 
    column_spacing = column_labels_and_spacing[0..-2].map(&:last) << 0 
    rows = h.map { |k,f| 
      [table_label[k]].product(f.map { |field, g| 
       [[field, g.values.map(&:to_s)].flatten] }) } 
      .flat_map { |e| e.map(&:flatten) }.unshift(column_labels) 
    column_widths = rows.transpose.map { |c| c.max_by(&:size).size } 
         .zip(column_spacing).map { |a,b| a+b } 
    rows.each do |row| 
    row.zip(column_widths).each { |s, width| print s.ljust(width) } 
    puts 
    end 
end 

输入

h = {"Table1"=> 
     {"Acct type"=>{"Expected"=>"ACC", "Actual"=>"ACC"}, 
     "Seq No" =>{"Expected"=>"100.0", "Actual"=>100}, 
     "Class" =>{"Expected"=>"AC", "Actual"=>"AC"}}, 
    "Table 2"=> 
     {"Date" =>{"Expected"=>"20140606", "Actual"=>"20130606"}}} 

column_labels_and_spacing = [["Table", 1], ["Field", 2], 
          ["Expected", 3], ["Actual"]] 
table_label = { "Table1"=>"Table 1", "Table 2"=>"Table 2" } 

为了简化我转换BigDecimal值到Fixnum说明。

Invoke方法

print_table(h, column_labels_and_spacing, table_label) 
    #-> Table Field  Expected Actual 
    # Table 1 Acct type ACC  ACC  
    # Table 1 Seq No  100.0  100  
    # Table 1 Class  AC   AC  
    # Table 2 Date  20140606 20130606 

说明

对于上面的例子:

column_labels = column_labels_and_spacing.map(&:first) 
    #=> ["Table", "Field", "Expected", "Actual"] 
column_spacing = column_labels_and_spacing[0..-2].map(&:last) << 0 
    #=> [1, 2, 3, 0] 

a = h.map { |k,f| 
     [table_label[k]].product(f.map { |field, g| 
     [[field, g.values.map(&:to_s)].flatten] }) } 
    # => [[["Table 1", [["Acct type", "ACC", "ACC"]]], 
    #  ["Table 1", [["Seq No", "100.0", "100"]]], 
    #  ["Table 1", [["Class", "AC", "AC"]]]], 
    # [["Table 2", [["Date", "20140606", "20130606"]]]]] 

要了解a进行计算,考虑第一键值对h传递给块,密钥被分配给所述块变量k和分配值,以f

k = "Table1" 
    f = { "Acct type"=>{ "Expected"=>"ACC", "Actual"=>"ACC" } } 

块然后执行以下计算:

b = f.map { |field, g| [[field, g.values.map(&:to_s)].flatten] } 
    # => [["Acct type", "ACC", "ACC"]] 

    c = ["Table 1"].product([[["Acct type", "ACC", "ACC"]]]) 
    #=> [["Table 1", [["Acct type", "ACC", "ACC"]]]] 

    d = c.flatten 
    #=> ["Table 1", "Acct type", "ACC", "ACC"] 

现在让我们进行的,具有计算a 。计算表中的所述主体的所述行:

e = a.flat_map { |e| e.map(&:flatten) } 
    #=> [["Table 1", "Acct type", "ACC", "ACC"], 
    # ["Table 1", "Seq No", "100.0", "100"], 
    # ["Table 1", "Class", "AC", "AC"], 
    # ["Table 2", "Date", "20140606", "20130606"]] 

然后添加列标签:

rows = e.unshift(column_labels) 
    #=> [["Table", "Field", "Expected", "Actual"], 
    # ["Table 1", "Acct type", "ACC", "ACC"], 
    # ["Table 1", "Seq No", "100.0", "100"], 
    # ["Table 1", "Class", "AC", "AC"], 
    # ["Table 2", "Date", "20140606", "20130606"]] 

接着,计算列宽度:

f = rows.transpose 
    #=> [["Table", "Table 1", "Table 1", "Table 1", "Table 2"], 
    # ["Field", "Acct type", "Seq No", "Class", "Date"], 
    # ["Expected", "ACC", "100.0", "AC", "20140606"], 
    # ["Actual", "ACC", "100", "AC", "20130606"]] 

g = f.map { |c| c.max_by(&:size).size } 
    #=> [7, 9, 8, 8] 

i = g.zip(column_spacing) 
    # => [[7, 1], [9, 2], [8, 3], [8, 0]] 

column_widths = i.map { |a,b| a+b } 
    #=> [8, 11, 11, 8] 

rows.each do |row| 
    row.zip(column_widths).each { |s, width| print s.ljust(width) } 
    puts 
end 

考虑第二印刷表格的行(列标签之后的第一行):

row = ["Table 1", "Acct type", "ACC", "ACC"] 
row.zip(column_widths) 
    # => [["Table 1", 8], ["Acct type", 11], ["ACC", 11], ["ACC", 8]] 

第一字段被打印:

s = "Table 1" 
width = 8 
print s.ljust(width); puts ?: 
    #Table 1 : 

其中I印刷结肠只是为了显示的字段宽度。其他字段的打印方式相似。

需要Ruby 1.9+才能知道首先将哪个键值对传递给块。