1

I have list of elements in a hash (%Hash).

I need to compare key elements each other and if one key matches with another key (with certain condition), then it would become a pair and should be stored it in HOA.

Here is my script:

use strict; use warnings;
use Data::Dumper;

my (%A, %Final);
my %Hash = (
            'Network=ROOT,Network=R16,Me=4462,Element=1,Node=1,Sec=1,Car=3' => 1,
            'Network=ROOT,Network=R16,Me=4462,Element=1,Equipment=1,Rack=1,Slot=1,Unit=1,DeviceSet=1,Device=1' => 1
);

foreach my $car (keys %Hash){
    if($car =~ m/Car=\d+/){
        if($car =~ /(.*),Node/){
            $A{$1} = $car;
        }
    }   
}
print Dumper(\%A);

foreach (keys %Hash){
    if($_ =~ m/$A{$_}(.*)(Device=\d+)$/){
        push @{$Final{$_}}, $A{$_};
    }
}

print "Final:\n".Dumper(\%Final);

Let's say in example, if any element contains Network=ROOT,Network=R16,Me=4462,Element=1 then if any other element contains above data as well as key ends with Device=\d+ then the both should become a key and array of values.

Current result:

$VAR1 = {
          'Network=ROOT,Network=R16,Me=4462,Element=1,Equipment=1,Rack=1,Slot=1,Unit=1,DeviceSet=1,Device=1' => [
                                                                                                                  undef
                                                                                                                ]
        };

Expected Result:

$VAR1 = {
          'Network=ROOT,Network=R16,Me=4462,Element=1,Equipment=1,Rack=1,Slot=1,Unit=1,DeviceSet=1,Device=1' => [
                                                                                                                  Network=ROOT,Network=R16,Me=4462,Element=1,Node=1,Sec=1,Car=3
                                                                                                                ]
        };

Why I am getting undef value in the HOA.

Update: I have updated the code, in the second hash iteration the code looks like this:

foreach my $ele (keys %Hash){
    foreach my $s_c(keys %A){
        if($ele =~ m/$s_c(.*)(Device=\d+)$/){
            push @{$Final{$ele}}, $A{$s_c};
        }
    }
}

I am able to get the desired result now. But is there any compact way to achieve this (since I am iterating hash within a hash).

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
vkk05
  • 3,137
  • 11
  • 25
  • 4
    Why did you ignore the warnings this code produces!?! `$A{$_}` is undef, and you know that none of the values of `%A` are undef, so no elements of `%A` has the value of `$_` for key. – ikegami Mar 18 '21 at 11:45
  • @ikegami : yes, there are warnings. I doubt whether this regex match is right or wrong? `if($_ =~ m/$A{$_}(.*)(Device=\d+)$/){` – vkk05 Mar 18 '21 at 11:50
  • 3
    No, there's no doubt. If it's throwing a warning, it's wrong. As the warning says, `$A{$_}` undefined. And that's clearly not what you intended. I shouldn't have to tell you that! – ikegami Mar 18 '21 at 12:02
  • 2
    This might be much easier to implement if you turn each line into a hash and use lookups on the values you care about. More code and more memory consumption, but easier to maintain compared to your pattern match, and it would support changing order of keys – simbabque Mar 18 '21 at 12:04
  • @ikegami I have updated the question. – vkk05 Mar 18 '21 at 14:07

1 Answers1

1

You can use maps to shorten your code. Here is the solution.

#!/usr/bin/perl

use strict; use warnings;
use Data::Dumper;

my (%A, %Final);
my %Hash = (
            'Network=ROOT,Network=R16,Me=4462,Element=1,Node=1,Sec=1,Car=3' => 1,
            'Network=ROOT,Network=R16,Me=4462,Element=1,Equipment=1,Rack=1,Slot=1,Unit=1,DeviceSet=1,Device=1' => 1
);

map {
    $A{$1} = $_ if $_ =~ m/Car=\d+/ && $_ =~ /(.*),Node/
} keys %Hash;

print Dumper(\%A);

map {
    my $ele = $_;
    map {
        my $s_c = $_;
        push @{$Final{$ele}}, $A{$s_c} if $ele =~ m/$s_c.*Device=\d+$/;
    } keys %A;
} keys %Hash;

print "Final:\n".Dumper(\%Final);
VPP
  • 41
  • 2