Perl - traversing hash of (hashes of hashes and scalars)? - perl

I have generated a hash that looks like this. (printed using Dumper)
$VAR1 = {
'sufia:s4655g60k' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '44d88612fea8a8f36de82e1278abb02f',
'checksum.old' => '44d88612fea8a8f36de82e1278abb02f',
'name' => 'eicar.com.txt',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/47/info%3Afedora%2Fsufia%3As4655g60k%2Fcontent%2Fcontent.0'
}
},
'sufia:9z9031393' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'b502be8d9e1286c94506c91c191c0b5a',
'checksum.old' => 'b502be8d9e1286c94506c91c191c0b5a',
'name' => 'Elsevier RightsLink Printable License.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/d9/info%3Afedora%2Fsufia%3A9z9031393%2Fcontent%2Fcontent.0'
}
},
'sufia:s4655g65z' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '1baaa38b3e7b6139b3847b7bb3b8644a',
'checksum.old' => '1baaa38b3e7b6139b3847b7bb3b8644a',
'name' => 'enso-crystal.jpg',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/3a/info%3Afedora%2Fsufia%3As4655g65z%2Fcontent%2Fcontent.0'
}
},
'sufia:d504rk35q' => {
'version.2' => {
'checksum.new' => '9e5422337c33fa83322fd287035e4ac5',
'checksum.old' => '9e5422337c33fa83322fd287035e4ac5',
'name' => '0501012.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/c4/info%3Afedora%2Fsufia%3Ad504rk35q%2Fcontent%2Fcontent.2'
},
'curVer' => 2,
'version.1' => {
'checksum.new' => 'a50e552f4776f1863050b89920c9f7eb',
'checksum.old' => 'a50e552f4776f1863050b89920c9f7eb',
'name' => '0501012.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/d1/info%3Afedora%2Fsufia%3Ad504rk35q%2Fcontent%2Fcontent.1'
},
'version.0' => {
'checksum.new' => 'b05398d3071808b880af4375f6cdf18d',
'checksum.old' => 'b05398d3071808b880af4375f6cdf18d',
'name' => '0501012.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/80/info%3Afedora%2Fsufia%3Ad504rk35q%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903124g' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'cd022d22cb5c46bf0e3f6c3b4c929ae1',
'checksum.old' => 'cd022d22cb5c46bf0e3f6c3b4c929ae1',
'name' => 'GT Contributor - Consent to Publish 2015-LindaNewman.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/04/info%3Afedora%2Fsufia%3A9z903124g%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903137j' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'c2a24f16cb62d765810af770510516d1',
'checksum.old' => 'c2a24f16cb62d765810af770510516d1',
'name' => 'ScholarAtUC-SplashPage-Revisions4-29-3F.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/99/info%3Afedora%2Fsufia%3A9z903137j%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903133f' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '9d1a7f558548815dbb8be639c315f367',
'checksum.old' => '9d1a7f558548815dbb8be639c315f367',
'name' => 'UCScienceNet Expansion Award Proposal-Isilon-To-APTrust.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/70/info%3Afedora%2Fsufia%3A9z903133f%2Fcontent%2Fcontent.0'
}
},
'sufia:9z9031279' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '6e763df35f2d807eac2763a87c6bb0bb',
'checksum.old' => '6e763df35f2d807eac2763a87c6bb0bb',
'name' => 'IMG_2221.JPG',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/52/info%3Afedora%2Fsufia%3A9z9031279%2Fcontent%2Fcontent.0'
}
},
'sufia:9z9031414' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '621a177b09602ce1f703dd4becd90fe8',
'checksum.old' => '621a177b09602ce1f703dd4becd90fe8',
'name' => 'MazdaLiveAssistance-Not.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/0d/info%3Afedora%2Fsufia%3A9z9031414%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903122x' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'a6653aac025f0eccbc5f96226923c79a',
'checksum.old' => 'a6653aac025f0eccbc5f96226923c79a',
'name' => 'example.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/41/info%3Afedora%2Fsufia%3A9z903122x%2Fcontent%2Fcontent.0'
}
},
'sufia:s4655g624' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '44d88612fea8a8f36de82e1278abb02f',
'checksum.old' => '44d88612fea8a8f36de82e1278abb02f',
'name' => 'NotAVirusIPromise.txt',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/c6/info%3Afedora%2Fsufia%3As4655g624%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903131w' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'f8f82d7f4d7a20839a20a9dd375f6478',
'checksum.old' => 'f8f82d7f4d7a20839a20a9dd375f6478',
'name' => 'UCScienceNet Expansion Award Proposal-LangsamLibrary.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/8d/info%3Afedora%2Fsufia%3A9z903131w%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903152n' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'e5c6bde4b0fa6c4f2e013656f6aa8bf5',
'checksum.old' => 'e5c6bde4b0fa6c4f2e013656f6aa8bf5',
'name' => '20950 dod.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/c9/info%3Afedora%2Fsufia%3A9z903152n%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903118b' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '99ada40eb1ad4c5f5bffe07108855dc6',
'checksum.old' => '99ada40eb1ad4c5f5bffe07108855dc6',
'name' => 'harvey1880.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/4d/info%3Afedora%2Fsufia%3A9z903118b%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903144z' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => 'a6653aac025f0eccbc5f96226923c79a',
'checksum.old' => 'a6653aac025f0eccbc5f96226923c79a',
'name' => 'example.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/f4/info%3Afedora%2Fsufia%3A9z903144z%2Fcontent%2Fcontent.0'
}
},
'sufia:9z9031350' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '23013ce2bb7203fff545cf6e9ec5ac4a',
'checksum.old' => '23013ce2bb7203fff545cf6e9ec5ac4a',
'name' => 'ScholarAtUC-SplashPage-Revisions4-29-1D.pdf',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/6e/info%3Afedora%2Fsufia%3A9z9031350%2Fcontent%2Fcontent.0'
}
},
'sufia:9z903129v' => {
'curVer' => 0,
'version.0' => {
'checksum.new' => '93fd70923362e02b4fb56bb137bcf1e2',
'checksum.old' => '93fd70923362e02b4fb56bb137bcf1e2',
'name' => 'DevTeam2.jpg',
'path' => '/opt/rails-apps/curate_app/jetty/fedora/default/data/datastreamStore/94/info%3Afedora%2Fsufia%3A9z903129v%2Fcontent%2Fcontent.0'
}
}
};
Have looked at How to iterate through Hash (of Hashes) in Perl? and couldn't get it work for me.
Need to traverse through all the keys that look like 'sufia:s4655g60k' and then for each of them, I need to extract 'curVer' and depending on the number of 'curVer' I need to cycle through 'version.0' to get the respective values of the keys.
How do I traverse this hash and read/update existing keys/values?

for my $key (keys(%$VAR1)) {
my $rec = $VAR1->{$key};
my $cur_ver = $rec->{curVer};
my $subrec = $rec->{"version.$cur_ver"};
my $checksum_new = $subrec->{'checksum.new'};
my $checksum_old = $subrec->{'checksum.old'};
my $name = $subrec->{name};
my $path = $subrec->{path};
...
}

Related

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

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

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'
}
],
},
);