0

Below is the small code snippet i have created using Hash Key and Hash Value which is an array. And my input is Hash value (Array in this case) , i have to search for all the arrays in $ENV hash and fetch the hash key

Example if i search for m3d1 , the output should be TEST3

  use strict;
  use warnings;
  use Data::Dumper;
  my %ENV;
  
  $ENV{"TEST3"}=["m3d1","m3d2"] ;
  $ENV{"TEST4"}=["m4d1","m4d2"] ;
  $ENV{"TEST5"}=["m5d1","m5d2"] ;
  $ENV{"TEST6"}=["m6d1","m6d2"] ;
  print Dumper \@keys;
  print Dumper \@values;

Is it possible , or is there a better design ?

1
  • 3
    Don't use %ENV as a variable name. There's an existing variable by that name. Commented Feb 5, 2021 at 7:52

1 Answer 1

1

Of course it's possible. We can visit every value in the data structure until we find the one that matches.

You didn't say what the strings represent, to I'm going to call TEST3 a group, and I'm going to call m3d1 a host. The following snippets don't assume a host is preset in only one of group.

my @groups;
for my $group (keys(%ENV)) {
   for my $host (@{ $ENV{$group} }) {
      if ($host eq $target_host) {
         push @groups, $group;
      }
   }
}

die("Not found\n") if !@groups;

say for @groups;

But this isn't efficient. If you were planning on doing many lookups, this would be slow.

Let's start by turning the structure inside out.

my %groups_by_host;
for my $group (keys(%ENV)) {
   for my $host (@{ $ENV{$group} }) {
      push @{ $groups_by_host{$host} }, $group;
   }
}

The above produces

my %groups_by_host = (
   m3d1 => [ "TEST3" ],
   m3d2 => [ "TEST3" ],
   m4d1 => [ "TEST4" ],
   m4d2 => [ "TEST4" ],
   m5d1 => [ "TEST5" ],
   m5d2 => [ "TEST5" ],
   m6d1 => [ "TEST6" ],
   m6d2 => [ "TEST6" ],
);

Then, searching becomes instantaneous.

my $groups = $groups_by_host{$target_host}
   or die("Not found\n");

say for @$groups;
Sign up to request clarification or add additional context in comments.

9 Comments

i get Global symbol "$key" requires explicit package name at test.pl .guess its groups , Thanks
Fixed. // I'm not sure what you're asking
Thank you , this seems to be a better approach . my $target_host="m4d1"; my $groups = $groups_by_host{$target_host} or die("Not found\n"); say for @$groups; I get the below error , Does it print the Key ? Bareword "say" not allowed while "strict subs" in use at test.pl line 34.
my ($name) = @$db_instance;
Or use $name = $group; instead of push @groups, $group;
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.