Hash dereference in Perl - perl

I have a HASH reference $job which has this data:
{
"opstat" : "ok",
"response": {
"group_id":23015,
"order_id":"139370",
"job_count":"10",
"credits_used":"100.45",
"currency":"USD"
}
}
I want to print the hash value of "response" key.
I tried doing this but did not work
print %{$job->{'response'}}
Edit
I do not want any formatting. I want to know how to access each element in the value of 'response' key.

I want to know how to access each element in the value of 'response' key.
By definition, you need some kind of loop. A foreach loop is typical, although you could also use map.
for my $key (keys %{$job->{response}}) {
my $val = $job->{response}{$key};
print("$key: $val\n"); # Or whatever
}
or
my $response = $job->{response};
for my $key (keys %$response) {
my $val = $response->{$key};
print("$key: $val\n"); # Or whatever
}

Try the following code, this is a real & complete script :
#!/usr/bin/env perl
use strict;
use warnings;
my $job = {
'opstat' => 'ok',
'response' => {
'currency' => 'USD',
'group_id' => ':23015',
'job_count' => '10',
'order_id' => '139370',
'credits_used' => '100.45'
}
};
foreach my $key (keys %{$job}) {
print "key=$key|value=$job->{$key}\n";
# Testing if "$job->{$key}" is a HASH ref
# ...if yes, we iterate inside the HASH
# through the next level.
if (ref($job->{$key}) eq "HASH") {
foreach my $key2 (keys %{$job->{$key}}) {
print "\tkey=$key2|value=$job->{$key}->{$key2}\n";
}
}
}
This is the output :
key=opstat|value=ok
key=response|value=HASH(0x1638998)
key=currency|value=USD
key=group_id|value=:23015
key=order_id|value=139370
key=job_count|value=10
key=credits_used|value=100.45
If you want to access "group_id" key :
print $job->{response}->{group_id};
If you only want to access "response" HASH without testing anything :
foreach my $key (keys %{$job->{response}}) {
print "key=$key|value=$job->{response}->{$key}\n";
}
or with with this while loop and each :
while (my ($key,$value) = each %{$job->{response}}){
print "key=$key|value=$value\n";
}

use Data::Dumper;
print Dumper( $job->{response} );
or individually ...
print $job->{response}{group_id};

I'm not quite sure what you're trying to achieve; your code would print the contents of the inner hash without any formatting. If you want a formatted output, you'd have to use the Data::Dumper module:
use Data::Dumper;
my $job = {
"opstat" => "ok",
"response" => {
"group_id":23015,
"order_id":"139370",
"job_count":"10",
"credits_used":"100.45",
"currency":"USD"
}
};
print Dumper($job->{'response'});

Related

how to parse the output of SOAP response which is in HASH format of data? see below code for details

#perl!
use warnings;
use strict;
use XML::Compile::SOAP;
use XML::Compile::SOAP11;
use XML::Compile::WSDL11;
use XML::Compile::Transport::SOAPHTTP;
use Data::Dumper;
##my other variables pointing to wsdl and xsd files.
my $url="http://myhost.com:9080/imws/services/ImpactManager/";
my %inargs_connect = (
"userName" => "xxxx",
"password" => "xxxxxxxxxx",
"imname" => "yyyyyyyyyyy",
"bufferType" => "abcd"
);
my $wsdl = XML::Compile::WSDL11->new;
$wsdl->addWSDL($wsdl_file);
$wsdl->compileCalls(address =>$url);
my ($answer, $trace) = $wsdl->call( 'Connect', %inargs_connect);
print ($answer);
the above code is printing :
HASH(0x47f8b28)
in the last print statement if i use dumper, i get the below response.
print Dumper($answer);
$VAR1 = {
'outargs' => {
'connectionId' => '1557666855346'
}
};
how to parse the required values like,
i need to be able to easily access 'connectionId' and '1557666855346' ?
Any ideas are welcome. Thanks in advance.
Thanks,
Kaushik KM.
$answer appears to be a hash reference, so you'd access the data using normal dereferencing techniques:
my $conn_id = $answer->{outargs}{connectionId};
print "$conn_id\n";
Output:
1557666855346
my %fhash = %{$answer};
my $key = "";
foreach $key (keys %fhash)
{
print "keys are\n \"$key\" its value is (${$answer}{$key}) \n";
foreach my $key2 (keys %${$answer}{$key})
{
print "keys of(${$answer}{$key})\n \"$key2\"\n";
}
}
is not working and is throwing error as follows:
Experimental keys on scalar is now forbidden at CreateEvent.pl line 64.
Type of arg 1 to keys must be hash or array (not key/value hash slice) at Create
Event.pl line 64, near "}
can someone correct this please.
loop through all the keys in answear = { outargs => { key1, key2 }}
# This should remove the error of "Experimental keys on scalar is now forbidden" by wrapping the hashRef in %{}
for ( keys %{$answear->{outargs}}) {
# $_ here will be the key and if you want to access the value use $answear->{outargs}->{$_}
print "key: $_, value: $answear->{outargs}->{$_}\n";
}
output:
key: connectionId, value: 1557666855346
I hope this will help you!

Printing Hash of Hash into a Matrix Table in Perl

I have a data structure like this:
#!/usr/bin/perl -w
my $hash = {
'abTcells' => {
'mesenteric_lymph_node' => {
'Itm2a' => '664.661',
'Gm16452' => '18.1425',
'Sergef' => '142.8205'
},
'spleen' => {
'Itm2a' => '58.07155',
'Dhx9' => '815.2795',
'Ssu72' => '292.889'
}
}
};
What I want to do is to print it out into this format:
mesenteric_lymph_node spleen
Itm2a 664.661 58.07155
Gm16452 18.1425 NA
Sergef 142.8205 NA
Dhx9 NA 815.2795
Ssu72 NA 292.889
What's the way to do it.
I'm currently stuck with the following code https://eval.in/44207
foreach my $ct (keys %{$hash}) {
print "$ct\n\n";
my %hash2 = %{$hash->{$ct}};
foreach my $ts (keys %hash2) {
print "$ts\n";
my %hash3 = %{$hash2{$ts}};
foreach my $gn (keys %hash3) {
print "$gn $hash3{$gn}\n";
}
}
}
Use Text::Table for output. Beautify to taste.
#!/usr/bin/env perl
use strict;
use warnings;
use Text::Table;
my $hash = {
'abTcells' => {
'mesenteric_lymph_node' => {
'Itm2a' => '664.661',
'Gm16452' => '18.1425',
'Sergef' => '142.8205'
},
'spleen' => {
'Itm2a' => '58.07155',
'Dhx9' => '815.2795',
'Ssu72' => '292.889'
}
}
};
my $struct = $hash->{abTcells};
my #cols = sort keys %{ $struct };
my #rows = sort keys %{ { map {
my $x = $_;
map { $_ => undef }
keys %{ $struct->{$x} }
} #cols } };
my $tb = Text::Table->new('', #cols);
for my $r (#rows) {
$tb->add($r, map $struct->{$_}{$r} // 'NA', #cols);
}
print $tb;
Output:
mesenteric_lymph_node spleen
Dhx9 NA 815.2795
Gm16452 18.1425 NA
Itm2a 664.661 58.07155
Sergef 142.8205 NA
Ssu72 NA 292.889
Now, the order of the rows above is different than the one you show because I wanted it to be consistent. If you know the set of all possible rows, then you can specify another order obviously.
First thing would be to separate out the two hashes:
my %lymph_node = %{ $hash->{abTcells}->{mesenteric_lymph_node} };
my %spleen = %{ $hash->{abTcells}->{spleen} };
Now, you have two separate hashes that contains the data you want.
What we need is a list of all the keys. Let's make a third hash that contains your keys.
my %keys;
map { $keys{$_} = 1; } keys %lymph_node, keys %spleen;
Now, we can go through all your keys and print the value for each of the two hashes. If one of the hashes doesn't have the data, we'll set it to NA:
for my $value ( sort keys %keys ) {
my $spleen_value;
my $lymph_nodes_value;
$spleen_value = exists $spleen{$value} ? $spleen{$value} : "NA";
$lymph_node_value = exists $lymph_node{$value} ? $lymph_node{$value} : "NA";
printf "%-20.20s %-9.5f %-9.5f\n", $key, $lymph_node_value, $spleen_value;
}
The printf statement is a nice way to tabularize data. You'll have to create the headings yourself. The ... ? ... : ... statement is an abbreviated if/then/else If the statement before the ? is true, then the value is the value between the ? and the :. Else, the value is the value after the :.
Both of your inner hashes have the same keys, So do a foreach on one of the hashes to get the key, and then print both.

how to declare array reference in hash refrence

my $memType = [];
my $portOp = [];
my $fo = "aster.out.DRAMA.READ.gz";
if($fo =~/aster.out\.(.*)\.(.*)\.gz/){
push (#{$memType},$1);
push (#{$portOp},$2);
}
print Dumper #{$memType};
foreach my $mem (keys %{$portCapability->{#{$memType}}}){
//How to use the array ref memType inside a hash//
print "entered here\n";
//cannot post the rest of the code for obvious reasons//
}
I am not able to enter the foreach loop . Can anyone help me fix it?
Sorry this is not the complete code . Please help me.
%{$portCapability->{#{$memType}}}
This doesn't do what you may think it means.
You treat $portCapability->{#{$memType}} as a hash reference.
The #{$memType} is evaluated in scalar context, thus giving the size of the array.
I aren't quite sure what you want, but would
%{ $portCapability->{ $memType->[0] } }
work?
If, however, you want to slice the elements in $portCapability, you would need somethink like
#{ $portCapability }{ #$memType }
This evaluates to a list of hashrefs. You can then loop over the hashrefs, and loop over the keys in an inner loop:
for my $hash (#{ $portCapability }{ #$memType }) {
for my $key (keys %$hash) {
...;
}
}
If you want a flat list of all keys of the inner hashes, but don't need the hashes themselves, you could shorten above code to
for my $key (map {keys %$_} #{ $portCapability }{ #$memType }) {
...;
}
I think what you want is this:
my $foo = {
asdf => {
a => 1, b => 2,
},
foo => {
c => 3, d => 4
},
bar => {
e => 5, f => 6
}
};
my #keys = qw( asdf foo );
foreach my $k ( map { keys %{ $foo->{$_} } } #keys ) {
say $k;
}
But you do not know which of these $k belongs to which key of $foo now.
There's no direct way to get the keys of multiple things at the same time. It doesn't matter if these things are hashrefs that are stored within the same hashref under different keys, or if they are seperate variables. What you have to do is build that list yourself, by looking at each of the things in turn. That's simply done with above map statement.
First, look at all the keys in $foo. Then for each of these, return the keys inside that element.
my $memType = [];
my $portOp = [];
my $fo = “aster.out.DRAMA.READ.gz”;
if ($fo =~ /aster.out\.(\w+)\.(\w+)\.gz/ ) { #This regular expression is safer
push (#$memType, $1);
push (#$portOp, $2);
}
print Dumper “#$memType”; #should print “DRAMA”
#Now if you have earlier in your program the hash %portCapability, your code can be:
foreach $mem (#$memType) {
print $portCapability{$mem};
}
#or if you have the hash $portCapability = {…}, your code can be:
foreach $mem (#$memType) {
print $portCapability->{$mem};
}
#Hope it helps

Traversing the hash of hash of array

Here is by code :
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $var = {
Cars => {
cars_name => [
"GT500",
"Beetle",
"P1800"
]
},
Bikes => {
Bikes_name => [
"Pulsar",
"Discover",
"CBR"
]
}
};
#Traversing the hash of hash of array
print "$var\n";
foreach my $k1 (keys %{$var}) {
print "$k1\n";
print $var->$k1;
#foreach my $k2 (keys %{$var->$k1}) {
#print"$k2\n";
#}
}
Whenever i am trying to print cars_name and Bikes_name , i am getting an error message saying the Can't call method Cars on Unblessed reference. I am not able to figure it out where am i doing mistake. Well, by mine understanding this print $var->$k1; line creating a prob. So please can any body help me out of this.
Thanks
print $var->$k1;
that is calling a method on an object. You want to access a hash:
print $var->{$k1};

Equivalent of "shift" for a hash to create a $class->next() method

I almost feel like saying "it's me again!".
Anyway, here we go.
I like using while $object->next() style constructs. They appeal to me and seem "neat".
Now, when the thing I'm iterating over is an array, it's straightforward ("shift #ary or return undef")
sub next {
my ( $self, $args ) = #_;
my $next = shift #{ $self->{list_of_things} } or return undef;
my ( $car, $engine_size, $color )
= split( /\Q$opts->{fieldsep}/, $next );
$self->car = $host;
$self->engine_size = $engine_size;
$self->color = $color;
}
In this example I use AUTOLOAD to create the getters and setters and then have those instance variables available in my object during the while loop.
I'd like to do something similar but with the "list_of_things" being a %hash.
Here's a non-OO example that doesn't make it into the first iteration. Any ideas why?
(The total "list_of_things" is not that big - maybe 100 entries - so to do a keys(%{$hash}) every time doesn't seem too wasteful to me).
use strict;
use warnings;
use Data::Dumper;
my $list_of_things = {
volvo => {
color => "red",
engine_size => 2000,
},
bmw => {
color => "black",
engine_size => 2500,
},
mini => {
color => "british racing green",
engine_size => 1200,
}
};
sub next {
my $args = $_;
my #list = keys( %{$list_of_things} );
return undef if scalar #list == "0";
my $next = $list_of_things->{ $list[0] };
delete $list_of_things->{ $list[0] };
return $next;
}
while ( next()) {
print Dumper $_;
print scalar keys %{ $list_of_things }
}
Is there a better way of doing this? Am I doing something crazy?
EDIT:
I tried Ikegami's suggestion. Of course, Ikegami's example works flawlessly. When I try and abstract a little, so that all that is exposed to the object is a next->() method, I get the same "perl-going-to-100%-cpu" problem as in my original example.
Here's a non-OO example:
use Data::Dumper qw( Dumper );
sub make_list_iter {
my #list = #_;
return sub { #list ? shift(#list) : () };
}
sub next {
make_list_iter( keys %$hash );
}
my $hash = { ... };
while ( my ($k) = next->() ) {
print Dumper $hash->{$k};
}
It does not seem to get past the first step of the while() loop.
I am obviously missing something here...
If you don't want to rely on the hash's builtin iterator (used by each, keys and values), there's nothing stopping you from making your own.
use Data::Dumper qw( Dumper );
sub make_list_iter {
my #list = #_;
return sub { #list ? shift(#list) : () };
}
my $list_of_things = { ... };
my $i = make_list_iter(keys %$list_of_things);
while (my ($k) = $i->()) {
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 0;
say "$k: " . Dumper($list_of_things->{$k});
}
The each operator is a builtin that iterates over hashes. It returns undef when it runs out of elements to return. So you could so something like
package SomeObject;
# creates new object instance
sub new {
my $class = shift;
return bless { hash_of_things => { #_ } }, $class
}
sub next {
my $self = shift;
my ($key,$value) = each %{ $self->{hash_of_things} };
return $key; # or return $value
}
Calling keys on the hash will reset the each iterator. It's good to know this so you can reset it on purpose:
sub reset {
my $self = shift;
keys %{ $self->{hash_of_things} }
}
and so you can avoid resetting it on accident.
The section on tie'ing hashes in perltie also has an example like this.
Here's how List::Gen could be used to create an iterator from a list:
use strict;
use warnings;
use List::Gen 'makegen';
my #list_of_things = ( # This structure is more suitable IMO
{
make => 'volvo',
color => 'red',
engine_size => 2000,
},
{
make => 'bmw',
color => 'black',
engine_size => 2500,
},
{
make => 'mini',
color => 'british racing green',
engine_size => 1200,
}
);
my $cars = makegen #list_of_things;
print $_->{make}, "\n" while $cars->next;
Well, if you don't need $list_of_things for later, you can always do something like
while(keys %$list_of_things)
{
my $temp=(sort keys %$list_of_things)[0];
print "key: $temp, value array: " . join(",",#{$list_of_things->{$temp}}) . "\n";
delete $list_of_things->{$temp};
}
And if you do need it, you can always assign it to a temporary hash reference and perform the same while loop on it.