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


Hello,

Need help on counting array elements in Hash of Arrays. How to list number of keys with respective to container number ?

%HoA = ( ## unique keys => [ "Item", "Container number" ], key1 => [ "50001", "01" ], key2 => [ "50011", "02" ], key3 => [ "50010", "01" ], key4 => [ "50041", "02" ], key5 => [ "50301", "02" ], key6 => [ "50701", "09" ], key7 => [ "50801", "09" ], );

Expected Output

No. of keys in the Container 01 : 2

No. of keys in the Container 02 : 3

No. of keys in the Container 09 : 2

Replies are listed 'Best First'.
Re: Count array element in HASH of ARRAYS
by stevieb (Canon) on Jul 20, 2015 at 13:47 UTC

    Because we have no clue how this hash is being constructed, nor do you show anything you've tried, I'll post here a (imho) better method of constructing your hash, and how to get what you want. Your HoA is very inefficient for the type of lookups you want to do, so I'd translate it into something more along the lines of:

    my %hoa = ( '01' => [ 50001, 50010, ], '02' => [ 50041, 50011, 50301, ], '09' => [ 50701, 50801, ], ); for my $k (keys %hoa){ my $count = @{ $hoa{$k} }; print "no of keys in container $k: $count\n"; }

    -stevieb

Re: Count array element in HASH of ARRAYS
by afoken (Chancellor) on Jul 20, 2015 at 13:44 UTC

    How would you do that manually? Explain it in a way that your grandmother or a five year old kid understands it. Translate that instructions to perl.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Count array element in HASH of ARRAYS
by halfcountplus (Hermit) on Jul 20, 2015 at 13:47 UTC
    #!/usr/bin/perl -w use strict; my %HoA = ( key1 => [ "50001", "01" ], key2 => [ "50011", "02" ], key3 => [ "50010", "01" ], key4 => [ "50041", "02" ], key5 => [ "50301", "02" ], key6 => [ "50701", "09" ], key7 => [ "50801", "09" ] ); my %containers; while (my ($k, $v) = each (%HoA)) { push @{$containers{$v->[0]}}, $k; } foreach (sort keys %containers) { print "Container $_ has ".@{$containers{$_}}." keys.\n" }
    This retains the keys in the `%containers` hash, if you don't need to do that you could replace the loops with:
    my %containers; while (my ($k, $v) = each (%HoA)) { $containers{$v->[1]}++; } foreach (sort keys %containers) { print "Container $_ has $containers{$_} keys.\n" }

      Just curious: Are the
          $containers{$con} = [ ] if !exists $containers{$con};
      or
          $containers{$con} = 0 if !exists $containers{$con};
      statements strictly (or warnings-ly) necessary with your Perl version? They aren't with 5.8.9 and 5.14.4 — but they certainly do no harm in any case.


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

        Seems they aren't necessary even with strict, no. I'm just prone to:
        use paranoid qw(really really);
        Which is not to say it's a good thing. In fact I'll take those out...they might be taken to improve readability or something but not significantly IMO.
        $containers{$con} = 0 if !exists $containers{$con};

        Above one works. Statement "Strictly" is in use and perl version is 5.10.1, no error / warning

      halfcountplus's method works. Thank you

        Yes, fine if this gives you what you want, but, you will notice that this solution first needs to reorganize the data structure into another data structure (%containers) to make the counting easy.

        So I think that you should really not neglect stevieb's useful comment (in post Re: Count array element in HASH of ARRAYS) that it might be better to build in the first place a data structure making your requirement easier to implement. It may or may not be possible in your specific case, but if there is a way of building something like %containers in the first place, then you are in a much easier solution.

Re: Count array element in HASH of ARRAYS
by neilwatson (Priest) on Jul 20, 2015 at 13:45 UTC

    Do you mean the number of elements in each array? If so:

    say "number of elements in key1 are ". scalar @{ $HoA{key1} }

    Neil Watson
    watson-wilson.ca

      I think he means how many of the first element in each array can be aggregated together where the second element in each array match ie. count the number of first elements where the second elems match.

Re: Count array element in HASH of ARRAYS
by Aldebaran (Curate) on Jul 20, 2015 at 22:49 UTC

    It seems to me that OP has the wrong data structure, trying to re-create the function of an array of hash references with a hash of hash references. If your keys are gonna be the integers, you might be as well go with an array of references, because then you get order. It makes the controls for looping easier.