I have a hash like below.
(
'cars' => {
'citroen' => {
'sedan' => { 'color' => 'red' },
'hatchback => { 'color' => 'white' },
'truck' => { 'color' => 'black' },
},
'ford' => {
'sedan' => { 'color' => 'red' },
'hatchback => { 'color' => 'white' },
'truck' => { 'color' => 'black' },
},
},
)
Car versions are sedan, hatchback and truck I want to get these versions and iterate over them. If sedan do.... If hatchback do...... If truck do....
I tried:
foreach my $key ( keys %{ $myhash->{'cars'}->{$carCompany} } ) {
print "\nCarVersion:" . $key;
}
But I couldn't get these versions.
I solved it.
foreach my $key (keys %{$myhash->{'cars'}->{'ford'}}) { print $key."\n"; }
this gives:
sedan
hatchback
truck
This was the output I wanted.
Related
I'm revisiting a perl application that I built several years ago. I have to rebuild some of it. But today I'm stuck. I'm having some trouble with hashes. I have this test script that loops through some hashes. What I don't understand is that the second time the last loop gives 'pid1' => $VAR1->[1]{'deal'}{'pid1'} as output. I'm expecting a hash with product data. What am I doing wrong?
#!usr/bin/perl
use strict;
use warnings;
use Data::Dumper qw(Dumper);
my %stores;
push #{$stores{'store1'}}, 'pid1';
push #{$stores{'store1'}}, 'pid2';
push #{$stores{'store2'}}, 'pid1';
print Dumper(\%stores);
my %products = (
'pid1' => {
'name' => 'Product 1',
'color' => 'red'
},
'pid2' => {
'name' => 'Product 2',
'color' => 'blue'
}
);
print Dumper \%products;
my #offers;
foreach my $storeid (keys %stores) {
foreach my $pid (#{$stores{$storeid}}) {
my %offer;
$offer{$storeid}{'deal'}{$pid} = $products{$pid};
push(#offers, %offer);
}
}
print Dumper(\#offers);
$VAR1 = {
'store1' => [
'pid1',
'pid2'
],
'store2' => [
'pid1'
]
};
$VAR1 = {
'pid2' => {
'name' => 'Product 2',
'color' => 'blue'
},
'pid1' => {
'color' => 'red',
'name' => 'Product 1'
}
};
$VAR1 = [
'store1',
{
'deal' => {
'pid1' => {
'color' => 'red',
'name' => 'Product 1'
}
}
},
'store1',
{
'deal' => {
'pid2' => {
'name' => 'Product 2',
'color' => 'blue'
}
}
},
'store2',
{
'deal' => {
'pid1' => $VAR1->[1]{'deal'}{'pid1'}
}
}
];
It means
$VAR1->[1]{'deal'}{'pid1'} # $offers[1]{'deal'}{'pid1'}
and
$VAR1->[5]{'deal'}{'pid1'} # $offers[5]{'deal'}{'pid1'}
are both references to the same hash, which looks like
{
'color' => 'red',
'name' => 'Product 1'
}
Maybe it's clearer if you use local $Data::Dumper::Purity = 1; to produce code that can actually be executed.
$VAR1 = [
'store1',
{
'deal' => {
'pid1' => {
'color' => 'red',
'name' => 'Product 1'
}
}
},
'store1',
{
'deal' => {
'pid2' => {
'name' => 'Product 2',
'color' => 'blue'
}
}
},
'store2',
{
'deal' => {
'pid1' => {}
}
}
];
$VAR1->[5]{'deal'}{'pid1'} = $VAR1->[1]{'deal'}{'pid1'};
I am trying to push values into hash. I want to add the values under 'par3'.
e.g.
$VAR1 = { 'obj1' => ['par1',
'par2',
'par3' => ['par4','par5','par6',....]]}
I should also be able to add elements into 'par3' in case 'obj1'-'par1'-'par2'-'par3' matches.
So far I have this, but I can't figure out how can I add "the second level" under 'par3':
push #{$a{$obj}},$par1,$par2,$par3
[ ... ] is a reference to an array. Array elements are scalars. So it is not possible to directly have the structure you seem to be requesting (ie. the par3 => [ ... ] pseudocode from your question). See perldsc
It's not obvious what you are trying to do but a couple of possible ideas might be to use a reference to a hash, or to replace the array with a hash:
use Data::Dumper;
$Var2a = {
'obj1' => [
'par1',
'par2',
{ 'par3' => undef, }
],
};
push #{ $Var2a->{obj1}[2]{par3} }, 'par4', 'par5', 'par6';
print Dumper $Var2a;
$Var2b = {
'obj1' => {
'par1' => undef,
'par2' => undef,
'par3' => undef,
},
};
push #{ $Var2b->{obj1}{par3} }, 'par4', 'par5', 'par6';
print Dumper $Var2b;
I think you want to add children to par3. As such, I think you want pars to have children. If so, you need a different data structure.
# Ordered
my $obj1 = [
{ name => 'par1', children => [ ] },
{ name => 'par2', children => [ ] },
{ name => 'par3', children => [
{ name => 'par4', children => [ ] },
{ name => 'par5', children => [ ] },
{ name => 'par6', children => [ ] },
] },
];
or
# Unordered
my $obj1 = {
par1 => { },
par2 => { },
par3 => {
par4 => { },
par5 => { },
par6 => { },
},
};
To append par7 to par3's children, you would use
# Ordered
use List::Util qw( first );
my $par7 = { name => 'par7', children => [ ] };
my $par3 = first { $_->{ name } eq 'par3' } #$obj1
or die( "par3 not found" );
push #{ $par3->{ children } }, $par7;
or
# Unordered
$obj1->{ par3 }{ par7 } = { };
I am facing an issue with the sort functionality on my Application. I need to sort my Hash of hashes on the lname key under the instructors. The legacy
application is written in Perl.
Here is the dump of the Hash which i need to sort.
$VAR1 = {
'instructors' => [
{
'is_placeholder' => 0,
'lname' => 'Lordy',
'name' => 'Daniel Lordy'
},
{
'is_placeholder' => 0,
'lname' => 'Fisher',
'name' => 'Bethy Fisher'
},
{
'is_placeholder' => 0,
'lname' => 'Jaya',
'name' => 'Jennifer Jaya'
},
],
'id' => '1237058',
'XXX' => {
'name' => 'Fall 2015 MFT Master 695',
},
'YYY' => '45'
};
The instructors key in the above structure can be empty as well.
For Example:
$VAR1 = {
'instructors' => [],
'id' => '1237058',
'XXX' => {
'name' => 'Fall 2015 MFT Master 695',
},
'YYY' => '45'
};
In my application, Users have an option to sort the column based on instructor names. So when user sorts by ascending order, the application should show rows which have instructors are empty at the start and then show the rest of the rows in which each row has the instructor names sorted in ascending order. Vice versa for Descending Order.
This is the code which I have tried until now.
if( $sort_order eq 'ASC' ) {
foreach my $elem ( #$course_sections ) {
my #sorted = map { $_->[1] }
sort { $a->[0] cmp $b->[0] }
map { [$_->{'lname'}, $_] } #{$elem->{'instructors'}};
}
if( $sort_order eq 'DESC' ) {
foreach my $elem ( #$course_sections ) {
my #sorted = map { $_->[1] }
sort { $b->[0] cmp $a->[0] }
map { [$_->{'lname'}, $_] } #{$elem->{'instructors'}};
}
How do I get this #sorted hash affect the order of rows in #$course_sections. Let me know if there is any easier way to do it.
Thanks in Advance.
You need to replace each instructors array ref with the sorted version that you created in your foreach loop. That way you get the instructors of each individual row sorted. Then you can sort the whole $course_sections by the name of the first instructor of each row.
# sort the instructors in-place
foreach my $elem (#$course_sections) {
$elem->{'instructors'} = [
map { $_->[1] }
sort { $a->[0] cmp $b->[0] }
map { [ $_->{'lname'}, $_ ] } #{ $elem->{'instructors'} }
];
}
# sort the courses by first instructor
$course_sections = [
map { $_->[1] }
sort { $a->[0] cmp $b->[0] }
map { [ ( $_->{'instructors'}->[0] ? $_->{'instructors'}->[0]->{'lname'} : q{} ), $_ ] }
#$course_sections
];
Make sure to replace undef values with empty strings so the cmp doesn't blow up. We shouldn't do $_->{'instructors'}->[0]->{'lname'} // q{} because autovivification might create a bunch of empty stuff in our data structure.
Here's your example data pulled together:
my $course_sections = [
{
'instructors' => [
{
'is_placeholder' => 0,
'lname' => 'Lordy',
'name' => 'Daniel Lordy'
},
{
'is_placeholder' => 0,
'lname' => 'Fisher',
'name' => 'Bethy Fisher'
},
{
'is_placeholder' => 0,
'lname' => 'Jaya',
'name' => 'Jennifer Jaya'
},
],
'id' => '1237058',
'XXX' => {
'name' => 'Fall 2015 MFT Master 695',
},
'YYY' => '45'
},
{
'instructors' => [],
'id' => '1237058',
'XXX' => {
'name' => 'Fall 2015 MFT Master 695',
},
'YYY' => '45'
}
];
And this is the output, dumped with Data::Printer.
\ [
[0] {
id 1237058,
instructors [],
XXX {
name "Fall 2015 MFT Master 695"
},
YYY 45
},
[1] {
id 1237058,
instructors [
[0] {
is_placeholder 0,
lname "Fisher",
name "Bethy Fisher"
},
[1] {
is_placeholder 0,
lname "Jaya",
name "Jennifer Jaya"
},
[2] {
is_placeholder 0,
lname "Lordy",
name "Daniel Lordy"
}
],
XXX {
name "Fall 2015 MFT Master 695"
},
YYY 45
}
]
I have some xml data, the dump looks like this:
$VAR1 = {
'Members' => [
{
'Age' => '19',
'Name' => 'Bob'
},
{
'Age' => '18',
'Name' => 'Jane'
},
{
'Age' => '21',
'Name' => 'Pat'
},
{
'Age' => '22',
'Name' => 'June'
}
],
'Sports' => [
{
'Players' => '20',
'Name' => 'Tennis'
},
{
'Players' => '35',
'Name' => 'Basketball'
}
],
};
I have tried the following code to print out the data:
foreach my $member (#($xml->{Members})) {
print("Age: $xml->{Age}");
}
But keep getting errors like:
Can't use string ("4") as a HASH ref while "strict refs" in use
Any idea why this won't work?
You are using the wrong syntax.
# here ... and here
# V V
foreach my $member (#($xml->{Members})) { ... }
To dereference, you need curly braces {}, not parenthesis ().
Once you've fixed that (which I think was a typo in the question, not in your real code), you have:
foreach my $member ( #{ $xml->{Members} } ) {
print "Age: $xml->{Age}";
}
But that's still wrong. You want to access the $member, not the whole $xml structure, because that doesn't have an Age, does it?
foreach my $member ( #{ $xml->{Members} } ) {
print "Age: $member->{Age}\n";
}
That will give you
Age: 19
Age: 18
Age: 21
Age: 22
I have some data in hashref format. I fetch data from graph.facebook.com
How to loop access?
$var = \{
'data' => [
{
'id' => '312351465029_10154168935475030',
'name' => 'Timeline Photos 1'
},
{
'name' => 'Bangchak\'s cover photo',
'id' => '312351465029_10154168087455030',
},
{
'id' => '312351465029_10154168081875030',
'name' => 'Timeline Photos 2',
}
],
'paging' => {
'previous' => 'https://graph.facebook.com/v2.6/312351465029/2',
'next' => 'https://graph.facebook.com/v2.6/312351465029/3'
}
};
These code Didn't work.
foreach $m ($var->{data})
{
if ( $m->{name} =~ /Timeline/i )
{
print "id = $m->{id}\n";
}
}
You need to dereference the array (perldoc perldsc):
use warnings;
use strict;
my $var = {
'data' => [
{
'id' => '312351465029_10154168935475030',
'name' => 'Timeline Photos 1'
},
{
'name' => 'Bangchak\'s cover photo',
'id' => '312351465029_10154168087455030',
},
{
'id' => '312351465029_10154168081875030',
'name' => 'Timeline Photos 2',
}
],
'paging' => {
'previous' => 'https://graph.facebook.com/v2.6/312351465029/2',
'next' => 'https://graph.facebook.com/v2.6/312351465029/3'
}
};
foreach my $m (#{ $var->{data} }) {
if ( $m->{name} =~ /Timeline/i )
{
print "id = $m->{id}\n";
}
}
__END__
id = 312351465029_10154168935475030
id = 312351465029_10154168081875030