Match key elements in same hash with regex and store it in HoA

75 views Asked by At

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).

1

There are 1 answers

0
VPP On

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);