Convert multilevel hash in simple hash in perl - perl

I have a hash that is multilevel hash i want to convert that into single level .But i am not able to do that
Actual Hash:
'MainSlab' => {
'A1' => {
'Slab' => {
'49_168' => {
'Amt' => '3000',
'Start' => '49',
'End' => '168'
},
'169_720' => {
'Amt' => '3000',
'Start' => '169',
'End' => '720'
},
'2_48' => {
'Amt' => '3000',
'Start' => '2',
'End' => '48'
},
'721_-' => {
'Amt' => '3000',
'Start' => '721',
'End' => '-'
}
}
},
'A2' => {
'Slab' => {
'49_168' => {
'Amt' => '3000',
'Start' => '49',
'End' => '168'
},
'169_720' => {
'Amt' => '4000',
'Start' => '169',
'End' => '720'
},
'2_48' => {
'Amt' => '5000',
'Start' => '2',
'End' => '48'
},
'721_-' => {
'Amt' => '3000',
'Start' => '721',
'End' => '-'
}
}
}
}
I want to convert that into simple and single level hash like this :
slab =>{
"49_168"=>{"A1"=> "3000","A2"=>"3000"},
"169_720"=>{"A1"=>"4000","A2"=>"4000"},
"2_48"=>{"A1"=>"5000","A2"=>"5000"},
"721_"=>{"A1"=>"3000","A2"=>"3000"}
}
Please help me to do this how can we do this

Assuming
my %hash = (
'MainSlab' => {
'A1' => {
'Slab' => {
'49_168' => {
'Amt' => '3000',
'Start' => '49',
'End' => '168'
},
'A2' => ...
);
Then:
my $hashref = $hash{'MainSlab'};
my $new_hashref = {};
foreach my $ax (keys %$hashref) {
foreach my $k (keys %{$hashref->{$ax}{'Slab'}}) {
$new_hashref->{$k}{$ax} = $hashref->{$ax}{'Slab'}{$k}{'Amt'};
}
}
my %new_hash = (slab => $new_hashref);
Will produce:
$new_hash = ( 'slab' => {
'49_168' => {
'A1' => '3000',
'A2' => '3000'
},
'169_720' => {
'A1' => '3000',
'A2' => '4000'
...
);

use Data::Dumper qw();
## actual hash $h1
my $h1 = { 'MainSlab' => { 'A1' => { 'Slab' => { '49_168' => { 'Amt' => '3000', 'Start' => '49', 'End' => '168' }, '169_720' => { 'Amt' => '3000', 'Start' => '169', 'End' => '720' }, '2_48' => { 'Amt' => '3000', 'Start' => '2', 'End' => '48' }, '721_-' => { 'Amt' => '3000', 'Start' => '721', 'End' => '-' } } }, 'A2' => { 'Slab' => { '49_168' => { 'Amt' => '3000', 'Start' => '49', 'End' => '168' }, '169_720' => { 'Amt' => '4000', 'Start' => '169', 'End' => '720' }, '2_48' => { 'Amt' => '5000', 'Start' => '2', 'End' => '48' }, '721_-' => { 'Amt' => '3000', 'Start' => '721', 'End' => '-' } } } } };
## transform to $h2
my #l2 = keys(%{$h1->{'MainSlab'}});
my #l1 = keys(%{$h1->{'MainSlab'}->{$l2[0]}->{'Slab'}});
my $h2 = {};
foreach my $l1 (#l1) {
my $inner = {};
foreach my $l2 (#l2) {
$inner->{$l2} = $h1->{'MainSlab'}->{$l2}->{'Slab'}->{$l1}->{'Amt'};
} ## end foreach
$h2->{'slab'}->{$l1} = $inner;
} ## end foreach
## print result
print(Data::Dumper->Dump([$h2],['$h2']));
Output:
$h2 = {
'slab' => {
'49_168' => {
'A1' => '3000',
'A2' => '3000'
},
'169_720' => {
'A1' => '3000',
'A2' => '4000'
},
'2_48' => {
'A1' => '3000',
'A2' => '5000'
},
'721_-' => {
'A1' => '3000',
'A2' => '3000'
}
}
};

Related

Perl dynamic hash of hash errors

I am looping over a query and returning results. I am trying to add a hash to another hashes. But running into trouble.
my %users_data;
while($sth->fetch)
{
$mygroup =>
{
'fname' => $fname,
'lname' => $lname,
'address' =>
{
'street' => $street,
'city' => $city,
},
'id' => $uid,
},
}
how do I add the $mygroup hash to %users_data hash?
long hand would be.
my %users_data = (
'salesmanager' =>
{
'fname' => 'mike',
'lname' => 'john',
'address' =>
{
'street' => '123 street',
'city' => 'Brooklyn',
},
'id' => 12,
},
'garagemanager' =>
{
'fname' => 'Mark',
'lname' => 'Jones',
'address' =>
{
'street' => '355 street',
'city' => 'Brooklyn',
},
'id' => 13,
},
)
Simply access the target key and assign its new value:
my %users_data;
while($sth->fetch)
{
$users_data{$mygroup} = {
'fname' => $fname,
'lname' => $lname,
'address' =>
{
'street' => $street,
'city' => $city,
},
'id' => $uid,
};
}

Converting hash to json format file [Perl]

So I created a function that creates a hash %data which looks as follows:
{
'10517' => {
'parent' => '10516',
'start' => 1545321095,
'end' => 1545321098,
'name' => 'A'
},
'10515' => {
'parent' => '10513',
'start' => 1545321091,
'end' => 1545321095,
'name' => 'B'
},
'10514' => {
'parent' => '10513',
'start' => 1545321091,
'end' => 1545321095,
'name' => 'C'
},
'10516' => {
'parent' => '10513',
'start' => 1545321091,
'end' => 1545321095,
'name' => 'D',
},
'10511' => {
'parent' => '#####',
'start' => 1545321090,
'end' => 1545321099,
'name' => 'E'
},
'10513' => {
'parent' => '10511',
'start' => 1545321091
'end' => 1545321097
'name' => 'F'
},
'10518' => {
'parent' => '10516',
'start' => 1545321094,
'end' => 1545321098,
'name' => 'G',
},
'10519' => {
'parent' => '10517',
'start' => 1545321096,
'end' => 1545321097,
'name' => 'H',
}
}
I would like to create a function which converts the data into the following output:
{
'children' : [
{
'id' : 10511,
'start' : 1545321090,
'end' : 1545321099,
'name' : 'E'
'children' : [
{
'id' : 10513,
'start' : 1545321091,
'end' : 1545321097,
'name' : 'F'
'children' : [
{
'id' : 10516,
'start' : 1545321091,
'end' : 1545321095,
'name' : 'D'
},
{
'id' : 10514,
'start' : 1545321091,
'end' : 1545321095,
'name' : 'C'
},
{
'id' : 10515,
'start' : 1545321091,
'end' : 1545321095,
'name' : 'B'
},
{
'id' : '10517',
'start' : 1545321095,
'end' : 1545321098,
'name' : 'A'
}
]
}
]
}
],
}
It is not the fully expected data (meaning I was too lazy to add the other ids into the nested format).
I would like to convert the hash %data to be contain a tree-type format as was showen in the example. The final goal is to have a nested data so each parent hash an array of each children, and each one of those children has an array of their own children (if they have of course), and so on.
How should I approch this problem? I'm looking for the cleanest and most effiecnt way possible. Also If possible, without any additional modules.
Just push the child elements into a children array in the parent:
use strict;
use warnings;
use Data::Dumper;
my $data =
{
'10517' => {
'parent' => '10516',
'start' => 1545321095,
'end' => 1545321098,
'name' => 'A'
},
'10515' => {
'parent' => '10513',
'start' => 1545321091,
'end' => 1545321095,
'name' => 'B'
},
'10514' => {
'parent' => '10513',
'start' => 1545321091,
'end' => 1545321095,
'name' => 'C'
},
'10516' => {
'parent' => '10513',
'start' => 1545321091,
'end' => 1545321095,
'name' => 'D',
},
'10511' => {
'parent' => '#####',
'start' => 1545321090,
'end' => 1545321099,
'name' => 'E'
},
'10513' => {
'parent' => '10511',
'start' => 1545321091,
'end' => 1545321097,
'name' => 'F'
},
'10518' => {
'parent' => '10516',
'start' => 1545321094,
'end' => 1545321098,
'name' => 'G',
},
'10519' => {
'parent' => '10517',
'start' => 1545321096,
'end' => 1545321097,
'name' => 'H',
}
};
my $root = [];
for my $id (keys %$data) {
my $entry = $data->{$id};
$entry->{id} = $id;
my $parent = $data->{$entry->{parent}};
unless ($parent){
push #$root, $entry
}
else{
push #{$parent->{children}},$entry;
}
}
print Dumper $root;
see
perldoc perldsc
for an introduction to nested data structures.

Accessing Specific OTRS Dynamic Field value via SOAP

How do I further access this dynamic field value? Upon using below dumper,
print Dumper( $Body->{$ResponseKey} );
The result is :
$VAR1 = {
'Ticket' => {
'Title' => 'TPLUS Service PIC',
'DynamicField' => [
{
'Value' => '43312',
'Name' => 'BugID'
},
{
'Value' => '6',
'Name' => 'OTRSMV'
},
{
'Value' => '6.13',
'Name' => 'OTRSPLV'
},
{
'Value' => 'Dev',
'Name' => 'OTRSUse'
},
{
'Value' => '2018-03-02 00:28:00',
'Name' => 'RefDate'
},
{
'Value' => '0',
'Name' => 'RefNumber'
},
{
'Value' => '',
'Name' => 'StartTime'
}
],
'StateType' => 'open',
'SLAID' => ''
}
};
How can I access the single value of DynamicField->RefDate ? Thanks
my $fields = $Body->{$ResponseKey}{Ticket}{DynamicField};
my ($ref_date) =
map $_->{Value},
grep $_->{Name} eq 'RefDate',
#$fields;
or
my %fields;
$fields{ $_->{Name} } = $fields{ $_->{Value} }
for #{ $Body->{$ResponseKey}{Ticket}{DynamicField} };
my $ref_date = $fields{RefDate};

Extracting data from a multi-level hash

I am getting the data structure below as a response from a web service call.
my $triggers1 = $zabbix->raw('trigger','get', $options1);
print Dumper($triggers1);
Output
$VAR1 = {
'10305122' => {
'hosts' => [
{
'name' => 'pc4b12cf254444',
'maintenance_type' => '0',
'hostid' => '19295'
}
],
'priority' => '1',
'status' => '0',
'dependencies' => [],
'templateid' => '9892568',
'comments' => '',
'state' => '0',
'triggerid' => '10305122',
'expression' => '{14127122}=0',
'error' => '',
'url' => '',
'flags' => '0',
'value' => '0',
}
324234' => {
'hosts' => [
{
'name' => 'pc45657ba34gy0423',
'maintenance_type' => '0',
'hostid' => '19439'
}
],
'priority' => '1',
'status' => '0',
'dependencies' => [],
'templateid' => '9896452',
'comments' => '',
'state' => '0',
'triggerid' => '10324234',
'expression' => '{14167689}=0',
'error' => '',
'url' => '',
'flags' => '0',
'value' => '0',
'value_flags' => '0',
'lastchange' => '1420266068',
'type' => '0'
};
etc
There are multiple similar records
From this output, I want to print the values of 'name' and 'value'.
How do I print this using Perl?
How about:
my $triggers1 = {
'10305122' => {
'hosts' => [
{
'name' => 'pc4b12cf254444',
'maintenance_type' => '0',
'hostid' => '19295'
}
],
'priority' => '1',
'status' => '0',
'dependencies' => [],
'templateid' => '9892568',
'comments' => '',
'state' => '0',
'triggerid' => '10305122',
'expression' => '{14127122}=0',
'error' => '',
'url' => '',
'flags' => '0',
'value' => '0',
},
324234 => {
'hosts' => [
{
'name' => 'pc45657ba34gy0423',
'maintenance_type' => '0',
'hostid' => '19439'
}
],
'priority' => '1',
'status' => '0',
'dependencies' => [],
'templateid' => '9896452',
'comments' => '',
'state' => '0',
'triggerid' => '10324234',
'expression' => '{14167689}=0',
'error' => '',
'url' => '',
'flags' => '0',
'value' => '0',
'value_flags' => '0',
'lastchange' => '1420266068',
'type' => '0'
}
};
Code disconnected from data for readability:
foreach my $k (keys %$triggers1) {
print "key=$k";
foreach my $h (#{$triggers1->{$k}{hosts}}) {
print "\nname=",$h->{name} // 'not defined';
// use this ^^ to avoid Use of uninitialized value in print at
}
print "\nvalue=",$triggers1->{$k}{value} // 'not defined',"\n";
}
Output:
key=324234
name=pc45657ba34gy0423
value=0
key=10305122
name=pc4b12cf254444
value=0

Perl printing second level hash keys in a nested hash

How do I print all my second level hash keys (sig_qtr, date, range, etc.) given a hash like such:
my $xml = XMLin("./${spec_file}", ForceArray => ['range', 'constant', 'question', 'date', 'sig_yr', 'sig_qtr', 'sig_mth'], KeyAttr => {});
print Dumper $xml->{entities};
print dumper output of hash:
$VAR1 = {
'sig_qtr' => [
{
'name' => 'q1',
'label' => 'q1'
},
{
'name' => 'q4',
'label' => 'q4'
}
],
'date' => [
{
'name' => 'y2_mth',
'label' => 'pryr_mth_curr'
},
{
'name' => 'y3_pod6_qtr4',
'label' => 'curr_qtd4'
}
],
'range' => [
{
'name' => 'y0_jun',
'end' => '20100631',
'start' => '20100601'
},
{
'name' => 'y3_oct',
'end' => '20131031',
'start' => '20131001'
}
],
'constant' => [
{
'spec' => '99999999 and 99999999',
'name' => 'none_sixmth'
}
],
'sig_yr' => [
{
'name' => 'y1_sig',
'label' => 'ye11'
},
{
'name' => 'y3_sig',
'label' => 'ytd'
}
],
'sig_mth' => [
{
'name' => 'y3_nov',
'label' => 'nov12'
},
{
'name' => 'y3_oct',
'label' => 'oct13'
}
],
'question' => [
{
'name' => 'ltrq',
'label' => 'q9'
},
{
'name' => 'nextprod',
'label' => 'q12a'
}
],
'backfill' => {
'label' => 'bf_period'
},
'year' => {
'current' => '2013'
}
};
would be even better if keys are put into an array.
Thanks.
print "$_\n" for keys %{ $xml->entities };
To put them into an array,
my #keys = keys %{ $xml->entities };