在Perl中,在相邻行中而不是在新行中打印大小和计数

y53ybaqx  于 2022-11-24  发布在  Perl
关注(0)|答案(1)|浏览(106)

我写了一个脚本,它将从数据库中获取值,并将其存储在名为total_hash的哈希中。
下一步我需要以表格的形式显示这些散列内容,所以使用了下面的逻辑将其显示在屏幕上。

#!/usr/bin/perl

use strict; use warnings;
use Data::Dumper;

my $method_total = 1;
my $method_a = 1;
my $method_b = 1;
my $method_sync = 1;

my %total_hash = (
  'Method_Combine' => {
              'flag' => 1,
              'count' => 27,
              'name' => '| Method TOTAL',
              'size' => 270
            },
  'Method_A' => {
                'count' => 7,
                'flag' => 1,
                'name' => '| Method A',
                'size' => 70
              },
  'Method_B' => {
                'count' => 20,
                'flag' => 1,
                'size' => 200,
                'name' => '| Method B'
              },
  'Method_Sync' => {
               'name' => '| Method Sync',
               'size' => 300,
               'flag' => 1,
               'count' => 30
             }
);
#print "total_hash:\n".Dumper(\%total_hash);

printReport(\%total_hash);

sub printReport {
    my $hash = shift;
    my $string1 = "";
    my $string2 = "";
    my $string3 = "";
    my $append_data = "";
    my $length = 20;
    my $total_length = $length * ($method_sync + $method_a + $method_b + $method_total) + 1;
    my @columns = ('Method_Sync','Method_A','Method_B','Method_Combine');

    foreach my $key (@columns) {
        if ($hash->{$key}->{flag}) {
            $append_data = sprintf("%-".$length."s",$hash->{$key}->{name});
            $string1 .= $append_data;
            $append_data = sprintf("%-".$length."s","| ".$hash->{$key}->{size}." Bytes");
            $string2 .= $append_data;
            $append_data = sprintf("%-".$length."s","| ".$hash->{$key}->{count});
            $string3 .= $append_data;
        }
    }
    print("Report:\n\n");
    print "-" x $total_length."\n";
    print $string1 . "|\n";
    print "-" x $total_length."\n";
    print $string2 . "|\n";
    print "-" x $total_length."\n";
    print $string3 . "|\n";
    print "-" x $total_length."\n";
}

此处内容打印如下(实际输出):

---------------------------------------------------------------------------------
| Method Sync       | Method A          | Method B          | Method TOTAL      |
---------------------------------------------------------------------------------
| 300 Bytes         | 70 Bytes          | 200 Bytes         | 270 Bytes         |
---------------------------------------------------------------------------------
| 30                | 7                 | 20                | 10                |
---------------------------------------------------------------------------------

我希望打印如下(预期结果):

-----------------------------------------------------------------------------------------------------------------------------------------------------------------
| Method Sync       | Method Sync Count | Method A          | Method A Count    | Method B          | Method B Count    | Method TOTAL      | Method TOTAL Count|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
| 300 Bytes         | 30                | 70 Bytes          | 7                 | 200 Bytes         | 20                | 270 Bytes         | 27                |
---------------------------------------------------------------------------------------------------------------------------------------------------------------

每种方法的大小和计数应该打印在相邻的一面,而不是打印在新的一行计数。如何做到这一点?

mwngjboj

mwngjboj1#

下面是一种根据需要设置显示格式的方法。
要使键名与其大小/计数对齐,请准备包含名称、值和宽度(名称和相应值之间的最大值)的列。然后将其布局:首先是带有标题的行,然后是带有相应数据的行,所有行都使用其列宽。根据喜好添加分隔符(请参见末尾的注解)

use warnings;
use strict;
use feature 'say';
#use Data::Dump qw(dd);
use List::Util qw(max);

my %total_hash = (
    'Method_Combine' => 
        { 'count' => 27, 'name' => 'Method TOTAL', 'size' => 270 },
    'Method_A' =>       
        { 'count' => 7,  'name' => 'Method A',     'size' => 70 },
    'Method_B' =>       
        { 'count' => 20, 'name' => 'Method B',     'size' => 200 },
    'Method_Sync' =>    
        { 'count' => 30, 'name' => 'Method Sync',  'size' => 300 }
);

my @keys = qw(Method_Sync Method_A Method_B Method_Combine);  # ordered

my @cols;
for (@keys) { 
    push @cols, { 
        header => $total_hash{$_}{name}, 
        data   => $total_hash{$_}{size} . ' Bytes',
        width  => max map { length } 
            ($total_hash{$_}{name}, $total_hash{$_}{size} . ' Bytes')
    };
    push @cols, { 
        header => $total_hash{$_}{name} . ' ' . 'Count',
        data   => $total_hash{$_}{count},
        width  => max map { length } 
            ($total_hash{$_}{name} . ' ' . 'Count', $total_hash{$_}{count})
    };
}
# dd \@cols;  # just to see it

my $hdr_str = '| ' . join(' | ', 
    map { sprintf "%-*s", $_->{width}, $_->{header} } @cols) . ' |';
my $dat_str = '| ' . join(' | ', 
    map { sprintf "%-*s", $_->{width}, $_->{data} }  @cols) . ' |';
my $sep = '-' x length $hdr_str;

say for $sep, $hdr_str, $sep, $dat_str, $sep;

打印

--------------------------------------------------------------------------------------------------------------------------------
| Method Sync | Method Sync Count | Method A | Method A Count |  Method B | Method B Count | Method TOTAL | Method TOTAL Count |
--------------------------------------------------------------------------------------------------------------------------------
| 300 Bytes   | 30                | 70 Bytes | 7              | 200 Bytes | 20             | 270 Bytes    | 27                 |
--------------------------------------------------------------------------------------------------------------------------------

我稍微更改了哈希和要求

  • 我将每一列的宽度设置为所需的宽度,而不是全部相同。这只需要 * 更多 * 的工作,如果你想让它们都是相同的宽度,这会更容易:找到所有名称和值的最大宽度并在任何地方使用它。那么就不需要width元素了
  • 我已经删除了字符串的纯格式化部分(|),它是name的值。这些条很容易根据需要添加(或者不添加,或者可以添加其他东西)
  • 我还删除了一个此处未使用的键/值(flag => 1),以便于查看

一旦我们准备好了标题和数据列,当然就有库来实现这个功能,比如文本模板和各种用于格式化/表格打印文本的模块。†然后还有Perl自己的format,更好的是Perl6::Form,但是sprintf在这里已经足够了。
关于样式的注意事项。经验表明,表格中额外的格式元素通常会分散注意力,而不是帮助。通常,分隔标题并在列之间留有足够的间距就足够了。除此之外,为了清晰起见,越少越好。也许可以考虑

Method Sync    Method Sync Count    Method A    Method A Count   
----------------------------------------------------------------    ...
 300 Bytes      30                   70 Bytes    7

†一些图书馆:第一个

相关问题