Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Printing from a hash table

by catfish1116 (Beadle)
on Jun 02, 2020 at 21:14 UTC ( [id://11117611]=perlquestion: print w/replies, xml ) Need Help??

catfish1116 has asked for the wisdom of the Perl Monks concerning the following question:

I'm working on this exercise to print out from a hash table. However, when I have an undefined value or a 'blank' value I don't want to print that out. Below is my code:

################################################### ## # ## 6/2/20 # ## Program prints out a report out of birthdays # ## hash table only if name AND birthday exist # ## in hash # ## # ################################################### my %birthdays = ( Fred => 'June 1', Ray => 'May 31', Glenn => 'May 27', Bob => 'August 28', Jim => '', Paul => undef, ); print"\nName Birthday\n"; print "-" x 25 ."\n"; foreach my $name ( keys %birthdays) { if (exists $birthdays{$name} ) { print " $name $birthdays{$name}\n"; } }

TIA The catfish

Replies are listed 'Best First'.
Re: Printing from a hash table
by haukex (Archbishop) on Jun 02, 2020 at 21:29 UTC

    You can use defined to test for undef and length to test for empty strings, and then either use an if to exclude those values like you're already using, or as an alternative use next to skip the current iteration of the loop.

    By the way, keys only returns the keys that already exist in the hash, so your exists check isn't necesary in this case.

Re: Printing from a hash table
by AnomalousMonk (Archbishop) on Jun 02, 2020 at 21:39 UTC
    foreach my $name ( keys %birthdays) {
        if (exists $birthdays{$name} ) {
            ...
        }
    }

    If you're iterating over the keys of a hash (as in the quoted code above), each key must exist in the hash! One way to do something like what you want:

    c:\@Work\Perl\monks>perl -wMstrict -e "my %birthdays = ( Fred => 'June 1', Ray => 'May 31', Glenn => 'May 27', Bob => 'August 28', Jim => '', Paul => undef, ); ;; my $fmt = ' %-10s %s'; printf qq{$fmt \n}, 'Name', 'Birthday'; print '-' x 25, qq{\n}; ;; B_DAY: foreach my $name (keys %birthdays) { next B_DAY unless defined $birthdays{$name} and length $birthdays{$name} ; printf qq{$fmt \n}, $name, $birthdays{$name}; } " Name Birthday ------------------------- Ray May 31 Bob August 28 Glenn May 27 Fred June 1


    Give a man a fish:  <%-{-{-{-<

Re: Printing from a hash table
by kcott (Archbishop) on Jun 03, 2020 at 06:56 UTC
Re: Printing from a hash table
by Tux (Canon) on Jun 03, 2020 at 08:11 UTC

    As 0 is most likely an invalid/undefined birthday too, you just want "true" values. All good advice already given, the shortest route might be:

    printf "%-12s %s\n", $_, $birthdays{$_} for grep { $birthdays{$_} } so +rt keys %birthdays;

    -->

    $ perl test.pl Name Birthday ------------------------- Bob August 28 Fred June 1 Glenn May 27 Ray May 31

    Enjoy, Have FUN! H.Merijn
Re: Printing from a hash table
by BillKSmith (Monsignor) on Jun 03, 2020 at 03:57 UTC
    When you need both the key and the value of a hash in a loop, the function each is convenient.
    use strict; use warnings; my %birthdays = ( Fred => 'June 1', Ray => 'May 31', Glenn => 'May 27', Bob => 'August 28', Jim => '', Paul => undef, ); while (my ($name, $B_day) = each %birthdays) { next if !defined $B_day or $B_day eq ''; printf "%9s : %-9s\n", $name, $B_day; }

    Output:>/

    Glenn : May 27 Fred : June 1 Ray : May 31 Bob : August 28
    Bill
      Careful, each has a nasty gotcha - iterator state! I personally never use it because of this and having been bit by it a few times.
      The iterator used by each is attached to the hash or array, and is shared between all iteration operations applied to the same hash or array. Thus all uses of each on a single hash or array advance the same iterator location. All uses of each are also subject to having the iterator reset by any use of keys or values on the same hash or array, or by the hash (but not array) being referenced in list context. This makes each-based loops quite fragile: it is easy to arrive at such a loop with the iterator already part way through the object, or to accidentally clobber the iterator state during execution of the loop body. It's easy enough to explicitly reset the iterator before starting a loop, but there is no way to insulate the iterator state used by a loop from the iterator state used by anything else that might execute during the loop body. To avoid these problems, use a foreach loop rather than while-each.
      
Re: Printing from a hash table
by soonix (Canon) on Jun 03, 2020 at 08:51 UTC
    • As haukex already stated, exists is superfluous, as keys can give you existing keys only, to loop over
    • for this purpose, undef and empty (and zero) are to be handled the same, you can simply test if/unless $birthdays{$name}. See Scalar values in perldata:
      A scalar value is interpreted as FALSE in the Boolean sense if it is undefined, the null string or the number 0 (or its string equivalent, "0"), and TRUE if it is anything else. The Boolean context is just a special kind of scalar context where no conversion to a string or a number is ever performed.
    (and just as I am composing this, Tux beat me to it :-) too much research and interruptions :-(
Re: Printing from a hash table
by Marshall (Canon) on Jun 03, 2020 at 07:05 UTC
    Some simple code:
    use warnings; use strict; my %birthdays = ( Fred => 'June 1', Ray => 'May 31', Glenn => 'May 27', Bob => 'August 28', Jim => '', Paul => undef, ); foreach my $name ( sort keys %birthdays) { next unless defined $birthdays{$name}; #skip undef next if $birthdays{$name} eq ''; #skip blank print "$name $birthdays{$name}\n"; } __END__ Bob August 28 Fred June 1 Glenn May 27 Ray May 31

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11117611]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2024-04-20 00:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found