Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Need some help with Hashes and formatting

by GreenLantern (Initiate)
on Jun 25, 2014 at 00:05 UTC ( #1091115=perlquestion: print w/ replies, xml ) Need Help??
GreenLantern has asked for the wisdom of the Perl Monks concerning the following question:

Hey folks, pretty experienced program in other languages but I'm crash learning perl for a new job. Following O'Reilly's Llama book. Decided to try something for myself to see if i understand things properly. heres what I have:

#!/usr/bin/perl my %hash = ("fred" => "flintstone", "dino" => undef, "barney" => "rubb +le", "betty" => "rubble"); my @ky = keys %hash; my @vals = values %hash; printf "%10s\t=>%10s\n", "keys", "values"; printf "%10s\t=>%10s\n" x @ky, @ky, @vals;

So what I'm trying to do if you don't know from seeing the above is get output that looks like two columns, first row has "keys => values" the subsequent rows has the keys and values in their respective columns but what I'm getting instead is this:

keys => values barney => betty dino => fred rubble => rubble => flintstone

(but it's of course formatted correctly in neat columns..... web-struggles) can someone tell me where I"m going wrong? I've done something like this but using only a single conversion and an array but now I'm trying to do it with the two conversions and it's not working out for me. Thanks!!!

Comment on Need some help with Hashes and formatting
Select or Download Code
Re: Need some help with Hashes and formatting
by toolic (Chancellor) on Jun 25, 2014 at 01:13 UTC
    This is a few more characters, but I think it's a little clearer than your code:
    printf "%10s\t=>%-10s\n", "keys", "values"; printf "%10s\t=>%-10s\n", $ky[$_], $vals[$_] for 0 .. $#ky; __END__ keys =>values barney =>rubble betty =>rubble dino => fred =>flintstone

    Does the book really show that code?

Re: Need some help with Hashes and formatting
by farang (Hermit) on Jun 25, 2014 at 03:01 UTC

    This statement
    printf "%10s\t=>%10s\n" x @ky, @ky, @vals;
    is first outputting all keys, then all values. Here's an alternative without the intermediate arrays, using the defined or operator // to avoid a warning on an undef value.

    #!/usr/bin/env perl use strict; use warnings; my %hash = ("fred" => "flintstone", "dino" => undef, "barney" => "rubble", "betty" => "rubble", ); printf "%10s\t=>%10s\n", "keys", "values"; for ( keys %hash ) { printf "%10s\t=>%10s\n", $_, $hash{$_} // ''; }

Re: Need some help with Hashes and formatting
by solegaonkar (Beadle) on Jun 25, 2014 at 03:38 UTC
    The first parameter after the x operator is expected to be a number - and the command is run as many times. If you provide an array, its count is considered for this count. The following @ky and @vals are just appended and the array of length 10 is fed as input to this huge command that prints out 10 strings. Hence you get this problem.

    Also, there is no guarantee about the order of of keys and values when you fetch them separately. You will have to fetch the keys first and then print values corresponding to each key. Try this out...
    my %hash = ("fred" => "flintstone", "dino" => undef, "barney" => "rubb +le", "betty" => "rubble"); my @keys = keys %hash; printf ("%10s\t=>%10s\n", "Keys", "Values"); map ((printf ("%10s\t=>%10s\n", $_, $hash{$_})), @keys);
      there is no guarantee about the order of of keys and values when you fetch them separately
      I'd call the documentation a guarantee:
      So long as a given hash is unmodified you may rely on keys, values and each to repeatedly return the same order as each other.
      لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        Thanks for correcting that! I never noticed that in the docs...
Re: Need some help with Hashes and formatting
by Laurent_R (Parson) on Jun 25, 2014 at 06:16 UTC
    It is really useless to use intermediary arrays. Use directly your hash:
    foreach my $key (keys %hash) { print "$key \t $hash{$key} \n"; }
    You might also take a look at the each function to fetch directly the key/value pairs.

    Get into the habit of using directly hashes rather than going into the trouble of using intermediary arrays, that's the only way to ge used to hashes and really leverage on their power.

    Edit: adding an example with the each function:

    while ( my ($key, $value) = each %hash) { printf "%10s\t%10s\n", $key, $value; }
Re: Need some help with Hashes and formatting
by LanX (Canon) on Jun 25, 2014 at 13:09 UTC
    if you just wanna dump the content of a hash, just use Data::Dumper ( or even better Data::Dump)

    DB<110> %hash = ("fred" => "flintstone", "dino" => undef, "barney" = +> "rubble", "betty" => "rubble"); DB<111> use Data::Dumper DB<112> print Dumper \%hash $VAR1 = { 'barney' => 'rubble', 'betty' => 'rubble', 'dino' => undef, 'fred' => 'flintstone' };

    and if you really need to avoid an explicit loop, then %hash in list context will give you keys and values correctly paired.

    DB<115> $length = 0 + keys %hash => 4 DB<116> printf "%10s\t=>%10s\n" x $length, %hash; barney => rubble betty => rubble dino => fred =>flintstone

    though for readability I'd rather prefer

    DB<123> $template = "%10s\t=>%10s\n" x (0 + keys %hash) %10s =>%10s %10s =>%10s %10s =>%10s %10s =>%10s DB<124> printf $template, %hash; barney => rubble betty => rubble dino => fred =>flintstone

    Cheers Rolf

    (addicted to the Perl Programming Language)

Re: Need some help with Hashes and formatting
by GreenLantern (Initiate) on Jun 25, 2014 at 15:05 UTC

    hey all, thanks for your responses. I learned a lot by looking at your different approaches to this. To answer Toolic's question, no, the book does not show this code. It shows an example problem:

    #!/usr/bin/perl print "enter several strings on different lines then ctrl+D\n"; chomp( my @lines = <STDIN> ); print "1234567890" x5 . "012345\n"; #a "ruler" for output field width printf "%20s\n"x@lines, @lines;

    and I wanted to expand on that form/function with using hashes too. just making more examples up for myself. thanks again! -Ben

Re: Need some help with Hashes and formatting
by Anonymous Monk on Jun 25, 2014 at 18:56 UTC

    hey all, thanks for your responses. I learned a lot by looking at your different approaches to this. To answer Toolic's question, no, the book does not show this code. It shows an example problem:

    #!/usr/bin/perl print "enter several strings on different lines then ctrl+D\n"; chomp( my @lines = <STDIN> ); print "1234567890" x5 . "012345\n"; #a "ruler" for output field width printf "%20s\n"x@lines, @lines;

    and I wanted to expand on that form/function with using hashes too. just making more examples up for myself. thanks again! -Ben

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1091115]
Approved by toolic
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2014-12-20 19:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (97 votes), past polls