Reputation: 716
I have a hash of array and hash which looks like follow:
$VAR1 = \{
'abc' => {
'def' => 'WorkSet',
'products' => [
{
'prodtype' => 'Dell',
'product' => 'Powerconnect-5600'
},
{
'prodtype' => 'Dell',
'product' => 'R-720'
},
{
'prodtype' => 'Dell',
'product' => 'R-920'
}
]
},
'123' => {
'456' => 'WorkSet',
'products' => [
{
'prodtype' => 'Dell',
'product' => '210'
},
{
'prodtype' => 'Dell',
'product' => 'TZ-200'
},
{
'prodtype' => 'Dell',
'product' => 'TZ-200'
},
]
}
}
I would like to have such that:
Branch: Workset
Build Number: abc
product : Dell producttype : PowerConnect-5600
product : Dell producttypr : R-720
product : Dell producttype : R-920
It should be same for the hash value 123 too.
I know to deference the above hash individually, but finding it difficult to do it in a loop.
Please give me your guidance.
FYI, I have listed the above hash using Data:Dumper perl module.
This is what I thought and tried but not getting the required answer in loops:
my @unique = uniq @version;
foreach $version(@ unique){
my $i=0;
print "$list->{$version}{branch}\n";
print "$list->{$version}->{products}->[$i]->{product}\n";
$i=$i+1;
} where @unique = qw (abc,123)
Upvotes: 0
Views: 195
Reputation: 716
This works too:
while (my ($build_num, $href) = each %$list) {
my ($branch, $aref, $username);
$aref = $href->{'products'};
$branch = $href->{branch};
$username = $href->{user};
for my $href (@$aref) {
print "product: $href->{prodtype} prodtype: $href->{product} qbs_id:$href->{qbs_id}\n";
}
Just edited @Chris answer with some simple modifications without using ref..Thank you
Upvotes: 0
Reputation: 107040
The question has already been answered and accepted, but I have to open my trap anyway...
First, I think your structure is off. It should look like this:
$VAR1 = {
'123' => bless( {
'ARRAY' => [
bless( {
'PRODUCT' => 'Dell',
'TYPE' => '210'
}, 'Product' ),
bless( {
'PRODUCT' => 'Dell',
'TYPE' => 'TZ-200'
}, 'Product' ),
bless( {
'PRODUCT' => 'Dell',
'TYPE' => 'TZ-200'
}, 'Product' )
]
}, 'Build' ),
'abc' => bless( {
'ARRAY' => [
bless( {
'PRODUCT' => 'Dell',
'TYPE' => 'Powerconnect-5600'
}, 'Product' ),
bless( {
'PRODUCT' => 'Dell',
'TYPE' => 'R-720'
}, 'Product' ),
bless( {
'PRODUCT' => 'Dell',
'TYPE' => 'R-920'
}, 'Product' )
]
}, 'Build' )
};
I base this on the output you want. It looks like you have Builds that consist of a list of products. The products consist of a Product Type and the Product Description. In your original structure you have:
`456` => Workset`
But this part of the structure makes no sense, and you don't use it. Maybe you meant this to be the Branch Type? It's hard to say. Let everything else I don't understand, I ignored it.
Now, how should you parse this structure? You should use Perl Object Oriented Programming. This allows you to stop worrying about your data structure. Your class definitions will take care of that. You don't have to worry if this was an array of hashes, or a hash or arrays, or maybe an array or arrays, of hashes.
Here's the entire main program. Two loops: In the first loop, I read in the data (consisting of three tab separated items: The Build Number, Prodtype, and Product). It's clear, short, and easy to understand. It takes just six lines of code to parse through your entire data structure:
use strict;
use warnings;
use feature qw(say);
my %workset;
my $prev_build;
#
# Read in the Data
#
while ( my $line = <DATA> ) {
chomp $line;
my ($build_num, $prodtype, $description) = split /\t/, $line;
my $product = Product->new( $prodtype, $description );
if ( not $prev_build or $prev_build ne $build_num ) {
$workset{$build_num} = Build->new;
$prev_build = $build_num;
}
$workset{$build_num}->Push($product);
}
#
# Parse the structure and Print it out
#
for my $workset ( sort keys %workset ) {
say "Build Number: " . $workset;
while ( my $product = $workset{$workset}->Pop ) {
say "Product: " . $product->Product . " Prodtype: " . $product->Type;
}
}
And here's the output:
Build Number: 123
Product: Dell Prodtype: TZ-200
Product: Dell Prodtype: TZ-200
Product: Dell Prodtype: 210
Build Number: abc
Product: Dell Prodtype: R-920
Product: Dell Prodtype: R-720
Product: Dell Prodtype: Powerconnect-5600
Just like you wanted.
The rest of my program is the class definitions. Most of the time, I simply append the definitions to the end of my main program because I never use them again. Still, using object oriented code makes programming faster and easier.
And here's the rest of my program:
package Product;
sub new {
my $class = shift;
my $product = shift;
my $type = shift;
my $self = {};
bless $self, $class;
$self->Product($product);
$self->Type($type);
return $self;
}
sub Product {
my $self = shift;
my $product = shift;
if ( defined $product ) {
$self->{PRODUCT} = $product;
}
return $self->{PRODUCT};
}
sub Type {
my $self = shift;
my $type = shift;
if ( defined $type ) {
$self->{TYPE} = $type;
}
return $self->{TYPE};
}
package Build;
use Carp;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
# PRIVATE -- No peeking
sub _Array_ref {
my $self = shift;
if ( not exists $self->{ARRAY} ) {
$self->{ARRAY} = [];
}
return $self->{ARRAY};
}
sub Index {
my $self = shift;
my $index = shift;
if ( not defined $self->{INDEX} ) {
$self->{INDEX} = 0;
}
if ( defined $index ) {
$self->{INDEX} = $index;
}
if ( $self->{INDEX} < 0 or $self->{INDEX} > $self->Size ) {
croak qq(Index out of range: Set to "$index");
}
return $self->{INDEX};
}
sub Array {
my $self = shift;
my @array = @{ $self->_Array_ref };
return wantarray ? @array : \@array;
}
sub Size {
my $self = shift;
my $array_ref = $self->_Array_ref;
return $#{ $array_ref };
}
sub Push {
my $self = shift;
my $product = shift;
if ( not defined $product or not $product->isa("Product") ) {
croak qq(Push Method for requires a Product Class to push);
}
my $array_ref = $self->_Array_ref;
push @{ $array_ref }, $product;
return $#{ $array_ref };
}
sub Pop {
my $self = shift;
my $array_ref = $self->_Array_ref;
return pop @{ $array_ref };
}
sub Next {
my $self = shift;
my $index = $self->Index;
my $array_ref = $self->_Array_ref;
$index += 1;
$self->Index($index);
return ${ $array_ref }[$index];
}
sub Prev {
my $self = shift;
my $index = $self->Index;
my $array_ref = $self->_Array_ref;
$index -= 1;
$self->Index($index);
return ${ $array_ref }[$index];
}
package main;
__DATA__
abc Dell Powerconnect-5600
abc Dell R-720
abc Dell R-920
123 Dell 210
123 Dell TZ-200
123 Dell TZ-200
Upvotes: 1
Reputation: 70722
However, I realize this is not exactly your data structure. I am providing an example of a way you could slightly go about a different approach.
use strict;
use warnings;
use feature 'say';
my $h = {
abc => {
Workset => {
Dell => [
'Powerconnect-5600',
'R-270',
'R-920',
],
},
},
123 => {
Workset => {
Dell => [
'210',
'TZ-200',
],
},
},
};
for my $k ( keys %$h ) {
for my $j ( keys %$h->{$k} ) {
for my $prod ( keys %$h->{$k}{$j} ) {
say "Branch: $j";
say "Build Number: $k";
say "product : $prod producttype : " . $_ for @{ $h->{$k}{$j}{$prod} };
}
}
}
Output:
Branch: Workset
Build Number: 123
product : Dell producttype : 210
product : Dell producttype : TZ-200
Branch: Workset
Build Number: abc
product : Dell producttype : Powerconnect-5600
product : Dell producttype : R-270
product : Dell producttype : R-920
Upvotes: 1
Reputation: 6573
This will dereference your structure (provided you have just 2 elements for each build number - the branch and the array or products). You have 'product' as 'prodtype', (eg prodtype => Dell
), in your hash and 'prodtype' as 'product' - reverse of names. You should consider improving your data structure as suggested by Jason Gray.
#!/usr/bin/perl
use strict;
use warnings;
my $hash = {
'abc' => {
'def' => 'WorkSet',
'products' => [
{
'prodtype' => 'Dell',
'product' => 'Powerconnect-5600'
},
{
'prodtype' => 'Dell',
'product' => 'R-720'
},
{
'prodtype' => 'Dell',
'product' => 'R-920'
}
]
},
'123' => {
'456' => 'WorkSet',
'products' => [
{
'prodtype' => 'Dell',
'product' => '210'
},
{
'prodtype' => 'Dell',
'product' => 'TZ-200'
},
{
'prodtype' => 'Dell',
'product' => 'TZ-200'
},
]
}
};
while (my ($build_num, $href) = each %$hash) {
my ($branch, $aref);
for my $key (keys %$href) {
if (ref($href->{$key}) eq 'ARRAY') {
$aref = $href->{$key};
}
else {
$branch = $href->{$key};
}
}
print "Branch: $branch\n";
print "Build Number: $build_num\n";
for my $href (@$aref) {
print "product: $href->{prodtype} prodtype: $href->{product}\n";
}
print "\n";
}
This prints output as:
Branch: WorkSet
Build Number: 123
product: Dell prodtype: 210
product: Dell prodtype: TZ-200
product: Dell prodtype: TZ-200
Branch: WorkSet
Build Number: abc
product: Dell prodtype: Powerconnect-5600
product: Dell prodtype: R-720
product: Dell prodtype: R-920
Upvotes: 1