Anonymous Monk has asked for the
wisdom of the Perl Monks concerning the following question:
Hi Monks!
I have an array like this:
$VAR1 = [
{
'name' => 'Discount',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Documents',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Money',
'reference' => '340 ',
'type' => 'Plastic'
},
{
'name' => 'State',
'reference' => '40 ',
'type' => 'Cotton'
},
{
'name' => 'Slice',
'reference' => '30 ',
'type' => 'Cotton'
}, {
'name' => 'Part',
'reference' => '45 ',
'type' => 'Cotton'
},
]
I would like to access the data in this array and
have the results as:
for ( @{ $my_array } )
{
print "$_\n";
}
print "Results: Paper:
Discount - 100
Documents - 100
Plastic:
Money - 340
Cotton:
State - 40
Slice - 30
Part - 45
Kind of lost on how to get this going, any help?
Thanks for the help!
Re: Accessing this array ref.
by SuicideJunkie (Vicar) on Apr 03, 2013 at 18:41 UTC
|
You have an array reference. Each element of the array is a hash reference.
So, when you loop, you are doing:
for my $hashRef ( @$my_array_ref ) # Curlies aren't needed here since
+$my_array_ref is a simple variable name
{
...
}
For each hash ref, you can inspect the contents via: $hashRef->{name} or $hashRef->{type} etc...
It looks like you want to spin through all the data and build a new Hash of Hashes (HoH):
$results->{$transactionType}{$purchasedThing} += $amountSpent
or some such like that.
When looping through the hashes to display, you probably want to sort the keys so that you print in the same order each time.
for my $transactionType (sort keys %$results)
{
for my $purchasedThings (sort keys %{ $results->{$transactionType} }
+) # Curlies here to mark out what to dereference
{
printf("spent \$%5d on %20s using %20s\n",
$results->{$transactionType}{$purchasedThings},
$purchasedThings,
$transactionType,
);
}
}
| [reply] [d/l] [select] |
|
your explanation makes sense, still having problems, I can print the first item from the array like this:
print $results->[0];
But running your code is giving me": Not a HASH reference". | [reply] [d/l] |
|
It sounds like you're defining $results somewhere that you haven't shown, and making it an array ref.
As I understand it, you want results to be a hash of hashes, so just declare it as my $results; or my $results = {};
| [reply] [d/l] [select] |
Re: Accessing this array ref.
by Loops (Curate) on Apr 03, 2013 at 18:58 UTC
|
You want to loop through the array, printing each item. Since the array is already sorted into groups, you just print a new group header when the value changes:
use feature 'say';
my $type;
for my $entry (@$VAR1) {
if ( $entry->{type} ne $type ) {
$type = $entry->{type};
say $type;
}
say "\t$entry->{name} - $entry->{reference}";
}
| [reply] [d/l] |
|
This would do it, I could combined all the data into one variable and print at once instead of printing them in the IF, right?
| [reply] |
|
I don't understand your question. If the data is sorted as Loops said, his solution should work for you.
| [reply] |
|
|
|
Re: Accessing this array ref.
by hdb (Monsignor) on Apr 03, 2013 at 21:30 UTC
|
use strict; use warnings;
my $VAR1 = [
{
'name' => 'Discount',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Documents',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Money',
'reference' => '340 ',
'type' => 'Plastic'
},
{
'name' => 'State',
'reference' => '40 ',
'type' => 'Cotton'
},
{
'name' => 'Slice',
'reference' => '30 ',
'type' => 'Cotton'
}, {
'name' => 'Part',
'reference' => '45 ',
'type' => 'Cotton'
},
];
my %results;
$results{$_->{type}}{$_->{name}} += $_->{reference} for (@{$VAR1});
print "Results:\n";
for my $type (keys %results) {
print "\t$type:\n";
for my $name (keys %{$results{$type}} ) {
print "\t\t$name - ".$results{$type}{$name}."\n";
}
}
| [reply] [d/l] |
Re: Accessing this array ref.
by arnaud99 (Beadle) on Apr 04, 2013 at 07:37 UTC
|
use Modern::Perl;
my $data = [
{
'name' => 'Discount',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Documents',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Money',
'reference' => '340 ',
'type' => 'Plastic'
},
{
'name' => 'State',
'reference' => '40 ',
'type' => 'Cotton'
},
{
'name' => 'Slice',
'reference' => '30 ',
'type' => 'Cotton'
}, {
'name' => 'Part',
'reference' => '45 ',
'type' => 'Cotton'
},
];
#recreate a data structure from the existing one,
#but this time the main key is the type.
my %result;
foreach my $elem(@$data)
{
my $type = $elem->{type};
#create an array ref for that type
if (! exists $result{$type} )
{
$result{$type} = [];
}
#store name an reference under that type
push @{ $result{$type} },
{
name => $elem->{name},
reference => $elem->{reference},
};
}
#loop through the new struct, and for each type,
#print the list of names and references
foreach my $a_type (sort {$a cmp $b} keys %result)
{
say $a_type;
foreach my $a_ref( @{ $result{$a_type} } )
{
say "\t", $a_ref->{name}, ': ', $a_ref->{reference};
}
}
Output
Cotton
State: 40
Slice: 30
Part: 45
Paper
Discount: 100
Documents: 100
Plastic
Money: 340
Cheers.
Arnaud | [reply] [d/l] [select] |
Re: Accessing this array ref.
by TJPride (Pilgrim) on Apr 04, 2013 at 12:34 UTC
|
If the original order isn't important, here's one alphabetically sorted:
use strict;
use warnings;
my $array = [
{
'name' => 'Discount',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Documents',
'reference' => '100 ',
'type' => 'Paper'
},
{
'name' => 'Money',
'reference' => '340 ',
'type' => 'Plastic'
},
{
'name' => 'State',
'reference' => '40 ',
'type' => 'Cotton'
},
{
'name' => 'Slice',
'reference' => '30 ',
'type' => 'Cotton'
}, {
'name' => 'Part',
'reference' => '45 ',
'type' => 'Cotton'
},
];
my %hash;
$hash{$_->{'type'}}{$_->{'name'}} = $_->{'reference'} for @$array;
print "Results:\n";
for my $k1 (sort keys %hash) {
print " $k1:\n";
for my $k2 (sort keys %{$hash{$k1}}) {
print " $k2 - $hash{$k1}{$k2}\n";
}
}
Output:
Results:
Cotton:
Part - 45
Slice - 30
State - 40
Paper:
Discount - 100
Documents - 100
Plastic:
Money - 340
| [reply] [d/l] [select] |
|
|