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

Hi Monks, I been thinking about how to do this for a few hours and I got no idea on how to do this. For Example : say i have this hash
$HASH{country}{fruits} = 1 where country can have value Canada , US , Taiwan , England etc.. where fruits can have value apples[AA-ZZ] , pears[AA-ZZ] , watermelons[AA-ZZ] etc so example database look would be : Country : Canada US Taiwan Fruits : apples applesAB applesZB pearsWE pearsDF watermelons orangesUPE orangesABC . . . . . . . . . note : different countries can have different number of elements in fr +uits
i want to be able to output to screen saying Canada , fruit pears something is missing from the list and say US and Taiwan are missing watermelon something , and oranges something is missign for US country , etc Any help?

20040904 Edit by castaway: Changed title from 'Searching Question'

Replies are listed 'Best First'.
Re: Reporting empty cells in a table of records
by bobf (Monsignor) on Sep 02, 2004 at 20:46 UTC

    Hi EchoAngel,

    If you want to find which elements are missing from a list, you've got to know the complete set of elements. I'm sure there's a better, more perlish way to do this (using grep, Quantum::Superpositions, Set::Scalar, Set::Bag?), but here is how I would do it.

    First, create a list of all the fruits. I don't quite understand how your AA-ZZ fits in, but it looks like 'pearsWE' eq 'pearsDF' so I'll assume they are not part of the name (I'm creating a new hash without those characters for simplicity). It also looks like all the fruit names are in lowercase, so I'll go on that assumption as well. Second, cycle through each country and check to see which elements are missing from the list of fruits.

    my ( %fruits, %newHASH ); # find all the fruit names foreach my $country ( keys %HASH ) { foreach my $fruit ( keys %{ $HASH{$country} } ) { $fruit =~ m/([a-z]+)[A-Z]+/; # [A-Z]+ included for distinction $fruits{$1}++; $newHASH{$country}{$1} = $HASH{$country}{$fruit}; } } # find which fruits are missing foreach my $country ( keys %newHASH ) { foreach my $fruit ( keys %fruits ) { if( not exists $newHASH{$country}{$fruit} ) { print "$country is missing $fruit!\n"; } } }

    BTW, if you don't need a hash for the fruits, a hash of arrays might be more appropriate than a hash of a hash. In other words, instead of using:

    %HASH $country $fruit = 1 $fruit = 1

    you might consider:

    %HASH $country = [ $fruit, $fruit... ]

    (which might make comparing lists easier).

    HTH

Re: Reporting empty cells in a table of records
by ccn (Vicar) on Sep 02, 2004 at 20:57 UTC

    This works on your data:

    #/usr/bin/perl -w use strict; my @idx; my @countries; open B, '< db.txt' or die $!; my $header = <B>; pos($header) = 1 + index $header, ':'; while ($header =~ /(\w+)/g) { push @idx, pos($header) - length($1); push @countries, $1; } while (<B>) { my ($fruit) = /\s([a-z]+)/; foreach (my $i = 0; $i < @idx; $i++) { print "$fruit missing for $countries[$i]\n" if length() <= $idx[$i] or substr($_, $idx[$i], length($countries[$i])) =~ /^\s+$ +/; } }

    Output:

    pears missing for Canada watermelons missing for US watermelons missing for Taiwan
Re: Reporting empty cells in a table of records
by Eimi Metamorphoumai (Deacon) on Sep 02, 2004 at 20:45 UTC
    Your question is a little confusing, but I think this will do it.
    my %HASH = ( Canada => {apples => 1, watermelons => 1, orangesUPE => 1}, US => {applesAB => 1, pearsWE => 1}, Taiwan => {applesZB => 1, pearsDF => 1, orangesABC => 1} ); my %countriesbyfruit; my %countries; while (my ($country, $fruithash) = each %HASH){ $countries{$country} = 1; for my $fruit (keys %$fruithash){ $fruit =~ s/[A-Z]+$//; $countriesbyfruit{$fruit}{$country} = 1; } } for my $fruit (keys %countriesbyfruit){ for my $country (keys %countries){ print "$country is missing $fruit\n" unless exists $countriesb +yfruit{$fruit}{$country}; } }