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

Hi, I am trying to compare values within a hash this way,
%hash=( key1 => [a,b,c,d,e,f], key2 =>[a,c,d,e,f], and o on... ); I want to compare key1[0] vs key2[0] key1[1] vs key2[1] and so on......
How do I do it? Please help me , Thanks in advance,

Replies are listed 'Best First'.
Re: compare values within hash
by ccn (Vicar) on Nov 23, 2008 at 15:18 UTC
    my @keys = keys %hash; for (my $i = 0; $i < @keys; $i++) { for (my $ii = $i+1; $ii < @keys; $ii++) { compare($hash{$keys[$i]}, $hash{$keys[$ii]}); } }
      That's really cool.Thanks to all of you,Appreciate it.
Re: compare values within hash
by toolic (Bishop) on Nov 23, 2008 at 15:15 UTC
    You have a Hash-of-Arrays structure. One way is to dereference each array, then loop through the arrays, comparing each element:
    use strict; use warnings; my %hash = ( key1 => [qw(a b c d e f)], key2 => [qw(a c d e f)] ); my @a1 = @{$hash{key1}}; my @a2 = @{$hash{key2}}; for my $i (0 .. $#a1) { unless (exists $a2[$i]) { print "No match for $a1[$i]\n"; next; } if ($a1[$i] eq $a2[$i]) { print "equal: $a1[$i], $a2[$i]\n"; } else { print "not equal: $a1[$i], $a2[$i]\n"; } } __END__ equal: a, a not equal: b, c not equal: c, d not equal: d, e not equal: e, f No match for f

      Using exists on array elements makes no sense. The information it returns is useless.

      my @a; $a[1] = undef; $a[2] = 'foo'; print("0: ", exists($a[0]) ?1:0,"\n"); # 0 print("1: ", exists($a[1]) ?1:0,"\n"); # 1 print("3: ", exists($a[3]) ?1:0,"\n"); # 0

      exists $a2[$i] should be $i < @a2 or defined $a2[$i] depending on what you were trying to accomplish.

        Using exists on array elements makes no sense.
        I disagree. It seems like the documentation to which you link also disagrees:
        Given an expression that specifies a hash element or array element, returns true if the specified element in the hash or array has ever been initialized, even if the corresponding value is undefined.
        It clearly mentions "array"; I must be missing your point.

        Here is what I was trying to accomplish. The OP has two arrays of different sizes. I decided to loop over the larger array (a1). In order to avoid a warning when checking the last element of a1 versus a non-existent element of the smaller array (a2), I decided to use exists. In my example, it Does What I Want.

        Thanks for pointing out $i < @a2; I definitely prefer it to my usage of exists in this case.

      That's one way to do it,But is it the best way? The values are already in the hash as arrays,Why should one store them again in separate ones?
        my @a1 = @{$hash{key1}}; my @a2 = @{$hash{key2}};

        You can avoid the copying by using references:

        my $a1 = $hash{key1}; my $a2 = $hash{key2}; ... if ($a1->[$i] eq $a2->[$i]) {

        which is functionally the same as

        if ($hash{key1}->[$i] eq $hash{key2}->[$i]) {

        but less to type if you need to access the arrays ($a1/$a2) more than once...