Re: Data Structures Help
by Arunbear (Prior) on Oct 29, 2004 at 12:31 UTC
|
You can use a hash of hashes like this:
use strict;
my %house;
my $room;
while (<DATA>) {
chomp;
next unless $_; # skip blank lines
if(/^\D/) { $room = $_ }
else { $house{$room}{$_}++ }
}
foreach my $room (keys %house) {
print "$room:\n";
print "width height quantity\n";
map { print "$_ $house{$room}{$_}\n"; }
sort { $house{$room}{$b} <=> $house{$room}{$a} }
keys %{$house{$room}};
}
__DATA__
office 1
120 120
120 120
140 135
155 135
120 120
bedroom 2
100 75
100 75
120 180
Outout:
bedroom 2:
width height quantity
100 75 2
120 180 1
office 1:
width height quantity
120 120 3
140 135 1
155 135 1
| [reply] [d/l] [select] |
Re: Data Structures Help
by tachyon (Chancellor) on Oct 29, 2004 at 12:32 UTC
|
my ($location, $h);
while(<DATA>){
chomp;
$location = $_ if m/^[a-zA-Z]/;
next unless m/(\d+)\s+(\d+)/;
$h->{$location}->{windows}++;
$h->{$location}->{frames}->{"$1x$2"}++;
$h->{$location}->{total_length}+= $1*2 + $2*2;
}
use Data::Dumper;
print Dumper $h;
my $fixed_cost_per_window = 100;
my $cost_by_material = 0.5;
my $total;
for my $location( keys %$h ) {
my $fixed = $h->{$location}->{windows} * $fixed_cost_per_window;
my $materials = $h->{$location}->{total_length} * $cost_by_materia
+l;
printf "%-10s\t%d windows \$%7.2f\tmaterials \$%7.2f\ttotal \$%7.2
+f\n",
$location, $h->{$location}->{windows}, $fixed, $materials, $fi
+xed+$materials;
$total += $fixed+$materials;
}
printf "\nTotal: \$%.2f\n", $total;
__DATA__
office 1
120 120
120 120
140 135
155 135
120 120
bedroom 2
100 75
100 75
120 180
This produces:
$VAR1 = {
'bedroom 2' => {
'frames' => {
'120x180' => '1',
'100x75' => '2'
},
'windows' => '3',
'total_length' => '1300'
},
'office 1' => {
'frames' => {
'155x135' => '1',
'140x135' => '1',
'120x120' => '3'
},
'windows' => '5',
'total_length' => '2570'
}
};
bedroom 2 3 windows $ 300.00 materials $ 650.00 total $ 950.
+00
office 1 5 windows $ 500.00 materials $1285.00 total $1785.
+00
Total: $2735.00
| [reply] [d/l] [select] |
Re: Data Structures Help
by hmerrill (Friar) on Oct 29, 2004 at 12:29 UTC
|
Got it.
Ok, I'm thinking you want a multi-dimensional hash. Here's basically what I'm talking about:
%windows = (
"office 1" => ("120 120" => 3,
"140 135" => 1,
"155 135" => 1),
"bedroom 2" => ("100 75" => 2,
"120 180" => 1),
);
That is a pre-loaded hash just to show you what the structure will look like. Of course you'll need to load that hash from scratch with your script as you read through the text file.
So in hash %windows, key "office 1" has a value which is a *reference* to an anonymous hash (a *reference* to an anonymous hash is created by the parenthesis), and that reference refers to the anonymous hash which has these key/value's:
Key Value
------- -----
120 120 3
140 135 1
155 135 1
Then to print out the %windows hash you will need two loops - one loop to iterate through the outer hash(with keys "office 1" and "bedroom 2", and an inner loop to iterate through the hash elements within each of those outer loop elements - something like this:
foreach my($room, $measurements_hashref) (each %windows) {
print "$room\n";
print "width\theight\tquantity\n";
foreach my($measurements, $count) (each %$measurements_hashref)
+{
print "$measurements $count\n";
}
}
***Careful - this is completely untested code, but hopefully it's close.
HTH. | [reply] [d/l] [select] |
Re: Data Structures Help
by Yendor (Pilgrim) on Oct 29, 2004 at 12:47 UTC
|
I'll to preface this with saying that the output is not EXACTLY in the format that you want...But it is readable, and the program does appear to work. I'm just a simple Perl hacker...With a little bit of elbow grease (which I don't necessarily know how to apply), this could become what you're looking for.
#!/usr/bin/perl -wT
use strict;
use Data::Dumper;
my $roomtype;
my $dim;
my $count;
my %output;
while (<DATA>) {
chomp;
# If the first character of the input is a letter, then we're on a n
+ew
# room type
if (/^[a-zA-Z]+/) {
$roomtype = $_;
$dim = undef;
} else {
$dim = join('_', split / /);
}
if (defined($roomtype) && defined($dim)) {
my $room = $roomtype . '_' . $dim;
if (defined($output{$room})) {
my $cur = $output{$room};
$cur++;
$output{$room} = $cur;
} else {
$output{$room} = 1;
}
}
}
my $data = Data::Dumper->new([\%output], [qw/*output/]);
print $data->Dump;
__DATA__
office 1
120 120
120 120
140 135
155 135
120 120
bedroom 2
100 75
100 75
120 180
And the output:
$ ./window.pl
%output = (
'bedroom 2_120_180' => 1,
'office 1_120_120' => 3,
'bedroom 2_100_75' => 2,
'office 1_155_135' => 1,
'office 1_140_135' => 1
);
| [reply] [d/l] [select] |
Re: Data Structures Help
by jdporter (Paladin) on Oct 29, 2004 at 12:32 UTC
|
my %windows;
my $current_location;
while (<>) { # read from stdin
chomp;
if ( /^\d+\s+\d+/ ) {
$current_location or die "bad input";
$windows{$current_location}{$_}++;
}
else {
$current_location = $_;
}
}
for my $location ( sort keys %windows )
{
print "\n$location\nwidth height quantity\n";
for my $dimensions { sort keys %{ $windows{$location} } ) {
print "$dimensions $windows{$location}{$dimensions}\n";
}
}
But /me smells homework. | [reply] [d/l] |
Re: Data Structures Help
by TedPride (Priest) on Oct 29, 2004 at 19:08 UTC
|
You can't use a straight hash of hashes because he seems to want the original order of office 1, bedroom 2, etc. preserved, and a hash won't do that. You also have to provide for there being empty lines.
use strict;
use warnings;
my (@arr, $ref);
while (<DATA>) {
chomp;
if (/^[a-zA-Z]/) { $arr[$#arr+1][0] = $_; }
elsif (/^\d/) { $arr[$#arr][1]{$_}++; }
}
foreach (@arr) {
print @$_[0] . "\n\n";
print "width height quantity\n\n";
$ref = @$_[1];
for (sort {$ref->{$b} <=> $ref->{$a} or $a cmp $b} keys %$ref) {
print "$_ " . $ref->{$_} . "\n\n";
}
}
__DATA__
office 1
120 120
120 120
140 135
155 135
120 120
bedroom 2
100 75
100 75
120 180
| [reply] [d/l] |
Re: Data Structures Help
by Anonymous Monk on Oct 29, 2004 at 11:59 UTC
|
Thanks for your reply. Sorry. The quantity field is what i am trying to generate from the text field. If a width and a height already exist for a given location, the quantity will increment (eg $count++). Thanks again. Does that make it clearer? | [reply] |
Re: Data Structures Help
by Anonymous Monk on Oct 30, 2004 at 13:26 UTC
|
Thankyou all for your great advise and examples. (Wow).
I have been trying to modify the examples to allow me to export the results to Microsoft Excel. I am trying to access each of the hash keys to allow me to place them into its own cell.
How can I use one of the above examples to allow me to do the following.
$worksheet->Cells($count,1)->{Value} = "$location";
$worksheet->Cells($count,1)->{Value} = "$width";
$worksheet->Cells($count,2)->{Value} = "$height";
$worksheet->Cells($count,3)->{Value} = "$quantity";
etc
In addition, I am also wanting to specify a type of film used with a given location
I was thinking that I could use tab spacing between the location name and the film type
For example the text file will look like this
office 3 \t safetyfilm
100 120
100 120
135 125
bedroom 1 \t windowtint
125 125
125 125
Then i would also export the film type into Excel
$worksheet->Cells($count,2)->{Value} = "$film";
Or should i place the type of film into the text file another way
Thankyou all again
Thankyou again for all your wisdom
| [reply] |
|
|
Why not just make the film another entry in the subhash? for example:
Office 1
Film => 'something',
'120 100' => 2
etc.
Then you have one per location, and you can easily separate it from the dimension counts by name.
-- Spring: Forces, Coiled Again!
| [reply] [d/l] |
Re: Data Structures Help
by hmerrill (Friar) on Oct 29, 2004 at 11:53 UTC
|
Where does the "quantity" column come from in your output? I don't see that in the input text file anywhere? Once I have a full picture of the input and output it will be easier to make a recommendation. | [reply] |
Re: Data Structures Help
by nimdokk (Vicar) on Oct 29, 2004 at 12:34 UTC
|
What have you tried so far? Why hasn't it worked? You might look at some sort of Hash of Hashes. | [reply] |