在可变宽度列中打印数组内容

时间:2011-08-25 21:16:25

标签: arrays perl printf dynamic-columns

我希望修改我的代码,使列扩展以容纳数据。

下面是一个断行的例子

+========+=========+===============+=============+=============+
| Record | Cluster | Current Build | Current Use | Environment |
+--------+---------+---------------+-------------+-------------+
| 3      | 1       | v44           | v44 Live (currently - new company cluster)| PROD        |
+--------+---------+---------------+-------------+-------------+

这是我正在使用的(kludgy)代码

sub printData {
   if (@_) {
      # print the data grid top border
      printf ("%10s%10s%15s%14s%14s",'+'.('=' x 8).'+',('=' x 9).'+',('=' x 15).'+',('=' x 13).'+',('=' x 13).'+');
      print "\n";
      # print the data grid column titles
      printf ("%-9s%-10s%-16s%-14s%-15s",'| Record ','| Cluster ','| Current Build ','| Current Use ','| Environment |');
      print "\n";

      # print out each row of data
      foreach my $rows (@_) {

         # print the data grid demarcation border
         printf ("%10s%10s%15s%14s%14s",'+'.('-' x 8).'+',('-' x 9).'+',('-' x 15).'+',('-' x 13).'+',('-' x 13).'+');
         print "\n";

         # print each data cell
         printf ("%-9s",'| '.$rows->{'Record ID#'});
         printf ("%-10s",'| '.$rows->{'Cluster'});
         printf ("%-16s",'| '.$rows->{'Current Build'});
         printf ("%-14s",'| '.$rows->{'Current Use'});

            # calculate the length of the last column
            my $length = length($rows->{'Environment'});

            # calculate how many spaces to add to the last column
            # the title of this column uses 15 characters (including '|' and spaces)
            # we already used three of those spaces for 2 '|' characters  and 1 leading space
            # so 15 - 3 = 12 
            # then subtract the length of the return string from 12
            my $spaces = 12 - $length;

         # we print the last data cell plus the padding spaces calculated above
         printf ("%-15s",'| '.$rows->{'Environment'}.(' ' x $spaces).'|');
         print "\n";
      }

      # we print the bottom data grid border
      printf ("%10s%10s%15s%14s%14s",'+'.('=' x 8).'+',('=' x 9).'+',('=' x 15).'+',('=' x 13).'+',('=' x 13).'+');
      print "\n";
    }
   else {  
      if ($debug) {
         print "trouble with printData subroutine\n";
      }
      return 0;
    }
}

4 个答案:

答案 0 :(得分:9)

Text::Table会调整列宽以适应数据。

答案 1 :(得分:3)

您必须预先扫描数据,确实获得每个字段的最大宽度,然后构建格式化字符串。

答案 2 :(得分:2)

Text::SimpleTable::AutoWidth非常直接,而且比Text :: Table更加繁琐。

答案 3 :(得分:2)

我不熟悉已经建议的任何一个模块,所以如果它们不能像你想的那样工作,那么我会像Mouse Food建议的那样做,并预扫描数据以获得每个模块的最大宽度柱。输出时,这些最大宽度将用于格式字符串。如果可能的话,在构建数组时获得此最大值可能更有效,而不是在结束时迭代两次。

下面的代码遍历整个数组以找到最大列长度,但是如果你在计算它时它应该很容易调整。另外,我已经把它从袖口上写下来并没有测试过,但它应该给你这个想法。

my %maximums = {
    "Record ID#" => 0,
    "Cluster" => 0,
    "Current Build" => 0,
    "Current Use" => 0
};

# calculate the maximum length of the values in each column
foreach my $row (@_) {
    foreach my $col (keys %maximums) {
        my $col_length = length($row->{$col});
        $maximums{key} = $col_length if ($col_length > $maximums{$col});
    }
}

# Generate a format string using the maximum column widths.  Other format strings
# may be generated in this loop for the other parts of the table.  Alternatively
# you could probably transform the one string and replace the characters in it.
my $row_format = "|";
foreach my $col (keys %maximums) {
    $row_format .= " %-",$maximums{$key},"s |";
}
$row_format .= "\n";

# Print your headers and borders here, using the other format strings that you
# would calculate above (where $row_format is generated).

# Print each row in the table
foreach my $row (@_) {
    printf($row_format, $row->{"Record ID#"}, $row->{"Cluster"},
        $row->{"Current Build"}, $row->{"Current Use"});
}