Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Count of HoA elements

by sweetblood (Parson)
on Jan 19, 2007 at 20:03 UTC ( #595560=perlquestion: print w/replies, xml ) Need Help??
sweetblood has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to get a total count of elements in a Hash of Arrays, but can't think or anyway short of iterating through the entire hash. I was thinking
my $count = scalar @{ values %hash };
should do it but I get "Can't use string ("###") as an array ref while "strict refs" in use." I know I can get the total by going through the hash and counting the number of elements for each, but would prefer not to.



Replies are listed 'Best First'.
Re: Count of HoA elements
by Fletch (Chancellor) on Jan 19, 2007 at 20:12 UTC

    Sounds like the typical impossible "I want to do iterative task X without iterating" request. Use List::Util and map and you can hide most of it, though.

    use List::Util qw( sum ); use YAML::Syck qw( Load ); my $hash = Load( do { local $/; <DATA> } ); my $count = sum( map { scalar @{ $hash->{ $_ } } } keys %${hash} ); print $count, "\n"; __END__ foo: - A - B - C bar: - D - E baz: - F - G - H

    Addendum: Just to make things clear: as others have below I'm interpreting "a total count of elements in a Hash of Arrays" to mean "a sum of the count of elements in each arrayref contained in a hash". And just to add more "twaddle", a Ruby version:

    require 'yaml' hash = YAML::load( <<EOT ) foo: - A - B - C bar: - D - E baz: - F - G - H EOT count = hash.values.inject(0) { |s,a| s += a.size } puts count ## O(1) version, akin to ikegami's below o_1_count = 0 hash.each_value { |a| o_1_count += a.size } ## Duuurh, Hash isa Enumerable so it has an inject itself or_even_count = hash.inject( 0 ) { | s, (k,v) | s += v.size }

    Addendum Update: Changed Ruby version to use hash.values rather than hash.keys, as seen below, which is actually a cleaner implementation than mine above. Also added (what should be :) an O(1) Ruby implementation. And also added using Hash#inject directly rather than iterating over values.

Re: Count of HoA elements
by ikegami (Pope) on Jan 19, 2007 at 20:15 UTC

    should do it

    No, it shouldn't. @{...} expects that ... retunrns a reference to an array. values %hash does not.

    anyway short of iterating through the entire hash.

    What do you think values does? Returns a list obtained by iterating through the entire hash.

    And whatever processes the list returned by value has to iterate over that list.

    These work:

    # time = O(N) memory = O(N*M) my $count = map @$_, values %h;
    # time = O(N) memory = O(N) my $count = sum map { scalar @$_ } values %h;
    # time = O(N) memory = O(N) my $count = 0; $count += @$_ for values %h;
    # time = O(N) memory = O(1) my $count = 0; while (my ($k, $v) = each(%h)) { $count += @$v; }

    Added 2nd and 4th solution.
    Added time and memory analysis.
    Choose the one that's the most readable and maintainable within your speed and memory requirements.

      Though I would not recomend using the second on big datastructures as it builds a list of all the elements in the arrays in the hash. Use either the first solution or

      use List::Util qw(sum); my $count = sum map scalar(@$_), values %h; #or # my $count = sum( map scalar(@$_), values(%h)); # or # my $count = sum( map {scalar(@$_)} values(%h)); # if that syntax looks more readable to you.

      Regarding the update: the first solution uses O(N) of memory where N is the number of elements of the hash, the second O(N*M) where M is the average length of the array in the hash. The List::Util solution is also O(N) memorywise.

        He asked for the number of elements in the HoA. I took that to mean 5 for the following structure:

        my %h = ( k1 => [ qw( a b c ) ], k2 => [ qw( d e ) ], );

        Your solution simply returns the number of elements in a hash. It could be that's what he meant, but that's now how I interpreted his question.

        This is wrong.

        Not so hasty on the wrong. Fletch and Jenda also interpreted the question like I did.

Re: Count of HoA elements
by BrowserUk (Pope) on Jan 19, 2007 at 20:06 UTC
Re: Count of HoA elements
by cormanaz (Chaplain) on Jan 19, 2007 at 22:11 UTC
    How about

    my $count = keys(%hash);


      Number of elements in a HoA $#{ $table{$ent}}

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://595560]
Approved by ww
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (6)
As of 2017-10-20 00:53 GMT
Find Nodes?
    Voting Booth?
    My fridge is mostly full of:

    Results (258 votes). Check out past polls.