http://qs1969.pair.com?node_id=502229

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

I'm trying to improve my perl-fu a bit, and I think this is a case where I could map or grep. However, it's not working the way I think it should, and I could use a nudge...

Now, a FAQ is How do I find out if a hash is empty?. That's not exactly what I want to do. I have a hash, I know there are keys out there, but I want to get a quick count of how many of those keys have non-empty values.

Here's a mini-case that I think should work (but doesn't):

#!/usr/bin/perl use strict; use Data::Dumper::Simple; my %a = ( one => 'red', two => '', three => 'blue' ); my @rtn = map {$a{$_} !~ /^$/;} keys(%a); print Dumper(@rtn); print "Keys w/ non-empty values: " . scalar(@rtn) . "\n"; __RESULTS__ @rtn = ( 1, 1, '' ); Keys w/ non-empty values: 3

I think that the matching operator is having its results stored in @rtn. Then, when I get use that return in scalar context, the result isn't quite what I was looking for. Now I have to figure out how many non-empties are in my array instead of my hash, which is pretty much where I started.

Thank you Monasterians...

Replies are listed 'Best First'.
Re: Count non-empty hash values
by fishbot_v2 (Chaplain) on Oct 22, 2005 at 17:34 UTC

    Try just greping:

    my $non_empty = grep { $a{$_} ne "" } keys %a; print "Keys with non-empty values: $non_empty\n"; __END__ Keys with non-empty values: 2

    You then need to decide whether undef of 0 entries are empty or not.

        and probably a tiny bit faster

        Yep, you've got me there, and then some:

        Rate OP other fishbot Joost OP 293/s -- -21% -76% -92% other 369/s 26% -- -69% -90% fishbot 1205/s 312% 226% -- -68% Joost 3723/s 1173% 908% 209% --

        "other" was a solution using values with a regex. "OP" was a corrected key and regex version of the OP's code.

        Update: Added OP-style solution to benchmark.

        Great answers fishbot_v2 and Joost.

        I figured out what threw me: In perldoc -f grep the code examples all use regex. I was mistaken when I thought grep just did the equivalent of "$_ =~ /myregex/". It does more than that. Even Programming Perl examples are of the regex type. For any future readers, I found a better example of the inequality usage (and some others) in Perl Cookbook, recipie 4.13.

        Also, kudos to Joost for using values(). I'm so used to calling by key with the arrow operator, that I comletely forgot that such a function existed.

Re: Count non-empty hash values
by swampyankee (Parson) on Oct 22, 2005 at 17:44 UTC
    Just to clarify (it's Saturday; I left several IQ points at the office): by empty do you mean the key exists but its value is undefined or do you mean the key exists but its value evaluates to false? My brute force and ignorance approach would be something like this for the first case:
    @values = values(%hash); foreach $i (@values) { $count ++ if defined($i); }
    or this for the second:
    @values = values(%hash); foreach $i (@values) { $count ++ if $i; }
    I also found that
    $count = (grep { /^$/ } values(%hash))- scalar(values(%hash);
    seems to work

    emc

Re: Count non-empty hash values
by Util (Priest) on Oct 22, 2005 at 17:34 UTC

    If you change your map to grep, then your code works correctly.