0

I have the following function which SHOULD return true or false when I look up a key and value in a hashref. I am sure I am missing something but what ?

The function shoudl return true or false if the key value strings that we search for are found.

#!/usr/bin/perl
use warnings;
use strict;
my $structure = {
    Key1 => {
           Key4 => "findme",
           Key5 => 9,
           Key6 => 10,
         },
    Key2 => {
           Key7 => "abc",
           Key8 => 9,
             },
 };

sub lookup_key_value
{
    # Arguments are a hash ref and a list of keys to find
    my($hash,$findkey, $findvalue) = @_;

        # Loop over the keys in the hash
        foreach my $hashkey ( keys %{$hash})
        {

            # Get the value for the current key
            my $value = $hash->{$hashkey};

            # See if the value is a hash reference
            if (ref($value) eq 'HASH')
            {
                    # If it is call this function for that hash
                    &lookup_key_value($value,$findkey,$findvalue);
            }

            if ( ($findkey =~ m/^$hashkey$/) && ( $value =~ m/^$findvalue$/) )
            {
                print "$findkey = $hashkey, $value = $findvalue\n";
                return (0);
            }
        }
        return (1);
}

if ( &lookup_key_value($structure,"Key7","abcX") )
{
    print "FOUND !\n";
} else {
    print "MISSING !\n";
}
Mike Rossi
  • 25
  • 4

2 Answers2

1
  1. This $findkey =~ m/^$hashkey$/ should be $hashkey =~ m/^$findkey$/
  2. You are returning 0, which translates to false in Perl, when matching key/value pair is found and returning 1 (true) when pair is not found. Why? Reverse this logic. To return false, use simple return;, without any arguments.
bart
  • 898
  • 4
  • 5
  • Thank you for the tips, I modified relevant code to: if ( ($hashkey eq $findkey) && ( $value eq $findvalue) ) { print "KEY $findkey = $hashkey, VALUE $value = $findvalue\n"; return (1); } } return; if ( &lookup_key_value($structure,"Key7","abc") ) { print "FOUND !\n"; } else { print "MISSING !\n"; } However I am still getting 'MISSING !' when modifying arguments to lookup function. Thank you – Mike Rossi Apr 02 '16 at 21:55
  • 1
    One more thing: functions in Perl should be called without the `&` character (except for some limited use cases). – bart Apr 02 '16 at 21:58
  • Right. You need to pass the result of recursive function call up, for example like this: change `lookup_key_value($value,$findkey,$findvalue);` to `if (lookup_key_value($value,$findkey,$findvalue)) { return 1; }` – bart Apr 02 '16 at 22:07
  • Thank you Bart, it works as expected after making the changes you suggested above. You have saved me a few extra hours of troubleshooting! You are awesome! – Mike Rossi Apr 02 '16 at 22:15
0

You're using the hash as an array of key/value pairs and not making use of the content addressing capability, which will can make this faster and much more concise. There's no need to check all the elements of every hash

#!/usr/bin/perl

use strict;
use warnings;

my $structure = {
    Key1 => { Key4 => "findme", Key5 => 9, Key6 => 10 },
    Key2 => { Key7 => "abc",    Key8 => 9 },
};

sub lookup_key_value {

    my ( $hash, $findkey, $findvalue ) = @_;

    my $val = $hash->{$findkey};

    if ( not ref $val ) {
        return 1 if defined $val and $val eq $findvalue;
    }

    for $val ( grep { ref eq 'HASH' } values %$hash ) {
        return 1 if lookup_key_value( $val, $findkey, $findvalue );
    }

    return;
}

print lookup_key_value( $structure, 'Key7', 'abcX' ) ? "FOUND !\n" : "MISSING !\n";

output

MISSING !
Borodin
  • 126,100
  • 9
  • 70
  • 144