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

hi monks,

i have a hash and want to simply check if items in an array are present in the hash. all of the items in the array should be in the hash, but i'm only finding 1873/ 1948.

can anyone suggest how I can find which keys in the hash are not matching to values in the array? The approach i have tried seems to just print everything many times over!

Kind regards

here is my code:

my %hash = map {$pids[$_] => $location_topology[$_]} 0 .. $#pids; print "size of hash: " . keys( %hash ) . ".\n"; #print @all_ids; #print "@all_ids\n"; while ( my ($key, $value) = each(%hash) ) { for (my $i=0; $i<@all_ids; $i++) { if ($all_ids[$i] eq $key) { print "$key => $value => $all_gc3s[$i]\n"; } # if ($all_ids[$i] ne $key) { #print "$key\n"; # } }

Replies are listed 'Best First'.
Re: stuck in a hash
by bart (Canon) on Aug 04, 2005 at 20:51 UTC
    You're not using the hash as it is intended. Instead, you're emulating a hash using a normal array... and you're looping though the hash like it was an array.

    So: reverse the hash and array in your test. Loop through the array, and let perl look it up in the hash for you.

    for my $i (0 .. $#all_ids) { my $key = $all_ids[$i]; if(exists $hash{$key}) { print "$key => $hash{$key} => $all_gc3s[$i]\n"; } else { print "Item '$key' is not in the hash.\n"; } }

    There. Probably lots faster.

Re: stuck in a hash
by davidrw (Prior) on Aug 04, 2005 at 20:50 UTC
    you can just do my @keys = keys %hash and then apply the Q&A node How can I find the union/difference/intersection of two arrays? to @keys and @all_ids.

    To modify your code, though, i would hash up the array first, and then just use the exists function:
    my %all_ids = map { $_ => undef } @all_ids; # note there's multiple w +ays to init this hash while ( my ($key, $value) = each(%hash) ) { printf "the pair (%s => %s) is not in the array", $key, $value unles +s exists $all_ids{$key}; } # or grep instead of while: my @missing_keys = grep( !exists $all_ids{$_}, keys %hash);
Re: stuck in a hash
by Eimi Metamorphoumai (Deacon) on Aug 04, 2005 at 21:08 UTC
    I can't quite figure out if you want the elements in the array but not the hash, or in the hash but not the array. But here's how to get both.
    my @not_in_hash = grep {!exists $hash{$_}} @all_ids; my %only_in_hash = %hash; #make a copy first delete @only_in_hash{@all_ids};
Re: stuck in a hash
by neniro (Priest) on Aug 04, 2005 at 23:10 UTC
    Using Perl6::Junction works fine too:
    #!/usr/bin/perl use strict; use warnings; use Perl6::Junction qw/none/; use Data::Dumper; my %colors = ( red => '#ff0000', blue => '#0000ff', green => '#00ff00', yellow => '#ffff00', ); my @sel_col = qw/ red green /; print Dumper [grep {none(@sel_col) eq $_} keys %colors];
Re: stuck in a hash
by neniro (Priest) on Aug 04, 2005 at 22:49 UTC
    I tried Quantum::Superpositions for this - and it seems to work fine:
    #!/usr/bin/perl use strict; use warnings; use Quantum::Superpositions; use Data::Dumper; my %colors = ( red => '#ff0000', blue => '#0000ff', green => '#00ff00', yellow => '#ffff00', ); my @sel_col = qw/ red green /; my @missing = eigenstates((any keys %colors) ne (all @sel_col)); print Dumper \@missing;