Perl printing second level hash keys in a nested hash - perl

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

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

Convert multilevel hash in simple hash in 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'
}
}
};

Create, populate and access a multi-dimensional array in Perl

I have the data structure (given below), can you please let me know how to populate and also to access the elements in the simplest form anytime I want. Which is the best way to implement, like Hash of Hashes or Array of Arrays or anything else ? There won't be too many elements in the array, the only problem is the its a multi-level kind of array
%Array = (
'Item0' => {
'Name' => 'Item0_Name',
'Attribs' => {
'Attr1' => {
'Name' => 'Attr1_Name',
'Num' => 'Attr1_Num'
},
'Attr2' => {
'Name' => 'Attr2_Name',
'Num' => 'Attr2_Num'
}
}
},
'Item1' => {
'Name' => 'Item1_Name',
'Attribs' => {
'Attr1' => {
'Name' => 'Attr1_Name',
'Num' => 'Attr1_Num'
},
'Attr2' => {
'Name' => 'Attr2_Name',
'Num' => 'Attr2_Num'
}
}
}
);
The official resource for this is the Perl Data Structure Cookbook (perldoc perldsc).
For the data shown, it seems that an array of hashrefs is sufficient since the keys shown in the OP are simply a stringified index. The same comment applies for 'Attribs':
my #array = (
{
'Name' => 'Item0_Name',
'Attribs' => [
{
'Name' => 'Attr1_Name',
'Num' => 'Attr1_Num'
},
{
'Name' => 'Attr2_Name',
'Num' => 'Attr2_Num'
}
],
},
{
'Name' => 'Item1_Name',
'Attribs' => [
{
'Name' => 'Attr1_Name',
'Num' => 'Attr1_Num'
},
{
'Name' => 'Attr2_Name',
'Num' => 'Attr2_Num'
}
],
},
);