Printing a hash of hashes using an array for the headings and getting the columns to line up

M

Mothra

Hi All,

I am trying to print out a report using a Hash of Hashes and am having
trouble
getting the columns to print out correctly. I have an array that contains
the column
headings in the correct order but I am stuck as how to get the HoH to use
this information. I have provided a test script as to what I have tried.
How can I get the script to print the columns in the correct order.

Thanks

Mothra



#!/app/perl5.8.0/bin/perl
use strict;
use warnings;

my @family = qw(UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS other);

my %people = (
'wattsl' => {
'SOLID_EDGE' => 3,
'WEBTOOLS' => 10,
'UNIGRAPHICS' => 19,
'UNIGRAPHICS_NX' => 57
},
'friasd' => {
'other' => 2,
'SOLID_EDGE' => 10,
'WEBTOOLS' => 25,
'UNIGRAPHICS' => 21,
'UNIGRAPHICS_NX' => 81
},
'yamaguch' => {
'other' => 4,
'SOLID_EDGE' => 12,
'WEBTOOLS' => 11,
'UNIGRAPHICS' => 9,
'UNIGRAPHICS_NX' => 56
},
'jung' => {
'other' => 2,
'SOLID_EDGE' => 5,
'WEBTOOLS' => 16,
'UNIGRAPHICS' => 13,
'UNIGRAPHICS_NX' => 39
},
'riches' => {
'other' => 2,
'SOLID_EDGE' => 18,
'WEBTOOLS' => 24,
'UNIGRAPHICS' => 10,
'UNIGRAPHICS_NX' => 83
},

);

printf "%24s %10s %10s %8s %5s \n", @family;

foreach my $person( sort keys %people ) {

printf "%9s %2d %2d %2d %2d %2d\n", $person,
map { $people{$person}{$_} } sort keys %{ $people{$person} };

}
 
D

David K. Wall

Mothra said:
I am trying to print out a report using a Hash of Hashes and am
having
trouble
getting the columns to print out correctly. I have an array that
contains the column
headings in the correct order but I am stuck as how to get the HoH
to use this information. I have provided a test script as to what
I have tried. How can I get the script to print the columns in the
correct order.

Thanks

Mothra



#!/app/perl5.8.0/bin/perl
use strict;
use warnings;

my @family = qw(UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS
other);

# Add this to construct a format strinf for printf()

my $form_str = '%9s ' . join '', map '%' . (1 + length $_) . 's'
=> @family;

my %people = (
'wattsl' => {
'SOLID_EDGE' => 3,
'WEBTOOLS' => 10,
'UNIGRAPHICS' => 19,
'UNIGRAPHICS_NX' => 57
},
'friasd' => {
'other' => 2,
'SOLID_EDGE' => 10,
'WEBTOOLS' => 25,
'UNIGRAPHICS' => 21,
'UNIGRAPHICS_NX' => 81
},
'yamaguch' => {
'other' => 4,
'SOLID_EDGE' => 12,
'WEBTOOLS' => 11,
'UNIGRAPHICS' => 9,
'UNIGRAPHICS_NX' => 56
},
'jung' => {
'other' => 2,
'SOLID_EDGE' => 5,
'WEBTOOLS' => 16,
'UNIGRAPHICS' => 13,
'UNIGRAPHICS_NX' => 39
},
'riches' => {
'other' => 2,
'SOLID_EDGE' => 18,
'WEBTOOLS' => 24,
'UNIGRAPHICS' => 10,
'UNIGRAPHICS_NX' => 83
},

);

printf "%24s %10s %10s %8s %5s \n", @family;

foreach my $person( sort keys %people ) {

printf "%9s %2d %2d %2d %2d %2d\n",
$person,
map { $people{$person}{$_} } sort keys %{ $people{$person}
};

}

printf "$form_str\n", ' ', @family;

foreach my $person( sort keys %people ) {
printf "$form_str\n", $person,
map { $people{$person}{$_} } @family;
}
 
M

Mothra

Hi David,

[snipped]

Thanks for replying :)
# Add this to construct a format strinf for printf()

my $form_str = '%9s ' . join '', map '%' . (1 + length $_) . 's'
=> @family;
Ok, generate a form.

[more snippage]
printf "$form_str\n", ' ', @family;

foreach my $person( sort keys %people ) {
printf "$form_str\n", $person,
map { $people{$person}{$_} } @family;
}
I added this and receive:
Use of uninitialized value in printf at F:\scripts\rep.pl line 52.
I think this is because of the wattsl value is missing the
'other' key value. After checking the orginal test script I found
that I was forcing a %2d in the format line.

I went back and reran the test script I orginally wrote and did not
receive the uninitialized value warning. I wonder why I did not receive
a warning? Any way, for now do you know of a good
way to remove the warning? (other that commenting out the use warnings
line).

Thanks

Mothra
 
D

David K. Wall

Mothra said:
I added this and receive:
Use of uninitialized value in printf at F:\scripts\rep.pl line 52.

I noticed the missing value and got the same warning message, but
since you didn't seem to care I didn't either.


foreach my $person( sort keys %people ) {
printf "$form_str\n", $person,
map { $people{$person}{$_} or 0 } @family;
}

Replace the '0' with whatever value is appropriate.
 
J

John W. Krahn

Mothra said:
I am trying to print out a report using a Hash of Hashes and am having
trouble getting the columns to print out correctly. I have an array that
contains the column headings in the correct order but I am stuck as how
to get the HoH to use this information. I have provided a test script as
to what I have tried. How can I get the script to print the columns in
the correct order.

[snip]

my @family = qw(UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS other);

[snip]

printf "%24s %10s %10s %8s %5s \n", @family;

foreach my $person( sort keys %people ) {

printf "%9s %2d %2d %2d %2d %2d\n", $person,
map { $people{$person}{$_} } sort keys %{ $people{$person} };
}


printf "%9s %2d %2d %2d %2d %2d\n",
$person, @{ $people{ $person } }{ @family };



John
 
M

Mothra

David K. Wall said:
[snipped]

I noticed the missing value and got the same warning message, but
since you didn't seem to care I didn't either.

Hmn, now I am confused, how did you come to the conclusion that I didn't
seem to care?
In my orginal post the code I posted did not generate the warning.
foreach my $person( sort keys %people ) {
printf "$form_str\n", $person,
map { $people{$person}{$_} or 0 } @family;
}

Replace the '0' with whatever value is appropriate.
Yep!! this works great!!!
Thanks very much!!

Mothra
 
D

David K. Wall

Mothra said:
David K. Wall said:
[snipped]

I noticed the missing value and got the same warning message, but
since you didn't seem to care I didn't either.

Hmn, now I am confused, how did you come to the conclusion that I
didn't seem to care?
In my orginal post the code I posted did not generate the warning.

I copied, pasted, and ran the original code unaltered, and got this
output:

Use of uninitialized value in printf at E:\perlprog\junk.pl line 50.
UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS other
friasd 10 21 81 25 2
jung 5 13 39 16 2
riches 18 10 83 24 2
wattsl 3 19 57 10 0
yamaguch 12 9 56 11 4


Looks like a warning to me.

Yep!! this works great!!!
Thanks very much!!

You're welcome.
 
M

Mothra

David K. Wall said:
Mothra said:
David K. Wall said:
[snipped]

I noticed the missing value and got the same warning message, but
since you didn't seem to care I didn't either.

Hmn, now I am confused, how did you come to the conclusion that I
didn't seem to care?
In my orginal post the code I posted did not generate the warning.

I copied, pasted, and ran the original code unaltered, and got this
output:

Use of uninitialized value in printf at E:\perlprog\junk.pl line 50.
[snipped]

I think I know what is going on.

F:\scripts>x.pl
UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS other
friasd 10 21 81 25 2
jung 5 13 39 16 2
riches 18 10 83 24 2
wattsl 3 19 57 10 0
yamaguch 12 9 56 11 4

F:\scripts>perl -v

This is perl, v5.6.1 built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)

I knew I was not going crazy.
then this.

F:\scripts>x.pl
UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS other
friasd 10 21 81 25 2
jung 5 13 39 16 2
riches 18 10 83 24 2
Use of uninitialized value in printf at F:\scripts\x.pl line 50.
wattsl 3 19 57 10 0
yamaguch 12 9 56 11 4

F:\scripts>perl -v

This is perl, v5.8.0 built for MSWin32-x86-multi-thread

I guess I need to use the latest version of perl, Sorry about that :)

Thanks

Mothra
 
A

Anno Siegel

Mothra said:
Hi All,

I am trying to print out a report using a Hash of Hashes and am having
trouble
getting the columns to print out correctly. I have an array that contains
the column
headings in the correct order but I am stuck as how to get the HoH to use
this information. I have provided a test script as to what I have tried.
How can I get the script to print the columns in the correct order.

Thanks

Mothra



#!/app/perl5.8.0/bin/perl
use strict;
use warnings;

my @family = qw(UNIGRAPHICS_NX UNIGRAPHICS SOLID_EDGE WEBTOOLS other);

my %people = (
'wattsl' => {
'SOLID_EDGE' => 3,
'WEBTOOLS' => 10,
'UNIGRAPHICS' => 19,
'UNIGRAPHICS_NX' => 57
},
'friasd' => {
'other' => 2,
'SOLID_EDGE' => 10,
'WEBTOOLS' => 25,
'UNIGRAPHICS' => 21,
'UNIGRAPHICS_NX' => 81
},
'yamaguch' => {
'other' => 4,
'SOLID_EDGE' => 12,
'WEBTOOLS' => 11,
'UNIGRAPHICS' => 9,
'UNIGRAPHICS_NX' => 56
},
'jung' => {
'other' => 2,
'SOLID_EDGE' => 5,
'WEBTOOLS' => 16,
'UNIGRAPHICS' => 13,
'UNIGRAPHICS_NX' => 39
},
'riches' => {
'other' => 2,
'SOLID_EDGE' => 18,
'WEBTOOLS' => 24,
'UNIGRAPHICS' => 10,
'UNIGRAPHICS_NX' => 83
},

);

printf "%24s %10s %10s %8s %5s \n", @family;

foreach my $person( sort keys %people ) {

printf "%9s %2d %2d %2d %2d %2d\n", $person,
map { $people{$person}{$_} } sort keys %{ $people{$person} };

}

I can't resist the temptation to plug my module Text::Table. Here
is how:

use Text::Table;

my $tb = Text::Table->new( 'name', @family);
$tb->add( $_, @{ $people{ $_}}{ @family}) for sort keys %people;

print $tb;

The advantage is that it figures out the alignment for you, that is,
you don't have to write and maintain the printf format.

Anno
 
M

Mothra

Hi Anno,

[snipped]
I can't resist the temptation to plug my module Text::Table. Here
is how:

use Text::Table;

my $tb = Text::Table->new( 'name', @family);
$tb->add( $_, @{ $people{ $_}}{ @family}) for sort keys %people;

print $tb;

The advantage is that it figures out the alignment for you, that is,
you don't have to write and maintain the printf format.
Oh, that is cool!!!
Off to CPAN I go :)

Mothra
 
D

David K. Wall

Anno Siegel said:
I can't resist the temptation to plug my module Text::Table. Here
is how:

use Text::Table;

my $tb = Text::Table->new( 'name', @family);
$tb->add( $_, @{ $people{ $_}}{ @family}) for sort keys
%people;

print $tb;

The advantage is that it figures out the alignment for you, that
is, you don't have to write and maintain the printf format.

I like it, and I have a project at hand for which it is very useful.
Thank you!

But there's one thing I haven't been able to figure out, and that's
how to right-align a column title. For example,

use Text::Table;
my $tb = Text::Table->new("TLA");
$tb->load( qw(188.52 0.00 97.36 185.51) );
print $tb;

produces

TLA
188.52
0.00
97.36
185.51

What I want to produce is

TLA
188.52
0.00
97.36
185.51


Maybe I'm being obtuse or haven't read the docs closely enough, but I
don't see how to do this.
 
A

Anno Siegel

David K. Wall said:
I like it, and I have a project at hand for which it is very useful.
Thank you!

But there's one thing I haven't been able to figure out, and that's
how to right-align a column title. For example,

use Text::Table;
my $tb = Text::Table->new("TLA");
$tb->load( qw(188.52 0.00 97.36 185.51) );
print $tb;

produces

TLA
188.52
0.00
97.36
185.51

What I want to produce is

TLA
188.52
0.00
97.36
185.51


Maybe I'm being obtuse or haven't read the docs closely enough, but I
don't see how to do this.

That's because you can't. Sorry.

In fact there's too little user control over alignment in more respects,
title-to-body alignment is just one of them. It will be the first thing
to fix if there is another release, but I'm not yet sure how to do it.

The problem isn't that these features are hard to implement, but how
to squeeze them into the user interface, which isn't exactly a beauty
to begin with. In fact, that's why I left them out in the first place,
that, and that I'd have to describe them all. I thought I'd get away
with it, but you're not the first to complain.

Anno
 
D

David K. Wall

Anno Siegel wrote:

[regarding Text::Table]
In fact there's too little user control over alignment in more respects,
title-to-body alignment is just one of them. It will be the first thing
to fix if there is another release, but I'm not yet sure how to do it.

The problem isn't that these features are hard to implement, but how
to squeeze them into the user interface, which isn't exactly a beauty
to begin with. In fact, that's why I left them out in the first place,
that, and that I'd have to describe them all. I thought I'd get away
with it, but you're not the first to complain.

I haven't examined the internals closely, so I may be way off-base here, but
since it already allows users to define columns with hashes, wouldn't that be
the obvious place to add new features for column formats? But I'd guess
you're looking at far more features than I have in mind, so I'll shut up
before I embarrass myself *too* much. :)
 
A

Anno Siegel

David K. Wall said:
Anno Siegel wrote:

[regarding Text::Table]
In fact there's too little user control over alignment in more respects,
title-to-body alignment is just one of them. It will be the first thing
to fix if there is another release, but I'm not yet sure how to do it.

The problem isn't that these features are hard to implement, but how
to squeeze them into the user interface, which isn't exactly a beauty
to begin with. In fact, that's why I left them out in the first place,
that, and that I'd have to describe them all. I thought I'd get away
with it, but you're not the first to complain.

I haven't examined the internals closely, so I may be way off-base here, but
since it already allows users to define columns with hashes, wouldn't that be
the obvious place to add new features for column formats?

That is very probably what will happen.
you're looking at far more features than I have in mind, so I'll shut up
before I embarrass myself *too* much. :)

I'm also playing with a more radical redesign where table columns would
become independent objects, but I think I'll go for a quick fix.

Anno
 
A

Anno Siegel

Anno Siegel said:
David K. Wall said:
Anno Siegel wrote:

[regarding Text::Table]

I haven't examined the internals closely, so I may be way off-base
here, but since it already allows users to define columns with hashes,
wouldn't that be the obvious place to add new features for column
formats?

That is very probably what will happen.

You can now (well, after the version propagates) control the alignment
of titles with the body through the key "align_title" in the
hash-specification, much like you suggested.

One feature draws another by the tail... So similarly, "align_title_lines"
controls the alignment of title lines among themselves for muiltiline
titles.

Anno
 
D

David K. Wall

[re Text::Table]
You can now (well, after the version propagates) control the
alignment of titles with the body through the key "align_title" in
the hash-specification, much like you suggested.

One feature draws another by the tail... So similarly,
"align_title_lines" controls the alignment of title lines among
themselves for muiltiline titles.

Oh my. I was reading the module and trying to understand how it works
so that /maybe/ I could send you a patch. So far all I had
accomplished was screwing things up. If you're ever in Cincinnati I'll
buy you a beer, or if not a beer, some Skyline chili. :)
 
J

John W. Krahn

David K. Wall said:
Oh my. I was reading the module and trying to understand how it works
so that /maybe/ I could send you a patch. So far all I had
accomplished was screwing things up. If you're ever in Cincinnati I'll
buy you a beer, or if not a beer, some Skyline chili. :)

Are you saying that beer and Skyline chili are interchangable in
Cincinnati? That's either strong beer or weak chili. :)


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top