Re: accesing a hash of an array of hashes
On May 26, 8:17 am, [EMAIL PROTECTED] (Pauld) wrote: > ive read a load of data in from a CSV file with Text::CSV and ended > up with a hash (%hash) where the keys are the column labels. > my @headings=split(/,/,$rows[0]) You're use()'ing Text::CSV, but you're not actually using Text::CSV. Why? > and then > > for (my $j=1;$j<$#rows;$j++) Is there a reason you're ignoring the last row completely? > { > my $status = $csv->parse ($rows[$j]); # parse a CSV string into > fields Storing the status is rather pointless if you don't bother actually checking it. . . > my @columns = $csv->fields (); # get the parsed fields > > for (my $i=0;$i<$#columns;$i++) Now you're ignoring the last column. Do you understand that $#foo is the *last index* of @foo, and so looping until less than $#foo stops before the last element? > {$hash{$headings[$i]}=$columns[$i];} Of course, that entire loop would be better served to be a hash slice... > > I want to process the data once its grouped by the date field present > in $hash. So i think I want a hash of dates where the key is that > date field > I push onto the value the hashes of the records that contain the date > > push @{$Hofdates{$hash{DATE}}},\%hash; > > but im having a problem working out how to access the individual > items in the hashes that are elements of the array You should read: perldoc perllol perldoc perldsc Go step by step: (1) %Hofdates is your overall hash. (2) $Hofdates{'2007-05-26'} is one element of the hash. That element is a reference to an array. (3) @{$Hofdates{'2007-05-26'}} is the array that (2) references. (4) ${$Hofdates{'2007-05-26'}}[0] is the first element of (3). That element is a reference to a hash. (5) %{${$Hofdates{'2007-05-26'}}[0]} is the hash that (4) references. (6) ${${$Hofdates{'2007-05-26'}}[0]}{NAME} is the value of (5) at the key 'NAME' (7) $Hofdates{'2007-05-26'}[0]{NAME} is the same as (6), but with all unnecessary punctuation removed. (See perldocs listed above) Once you get used to Perl's multi-level structures, you'll find you don't need to go through this process, as the end result just "makes sense". Please note, whenever possible, please try to post a short-but- complete script that demonstrates what you're trying to do. That way we can help you see what you might have done wrong. For example: #!/usr/bin/perl use strict; use warnings; use Text::CSV; use Data::Dumper; my $csv = Text::CSV->new(); my %records_for; my $heading = ; $csv->parse($heading) or die "Could not parse '$heading'. Failed on " . $csv- >error_input; my @heading = $csv->fields(); while (my $line = ) { $csv->parse($line) or die "Could not parse line $.. Failed on " . $csv->error_input; my @columns = $csv->fields(); my %hash; #use a hash slice rather than a for loop. @[EMAIL PROTECTED] = @columns; push @{$records_for{$hash{DATE}}}, \%hash; } #Take a look at your structure. print Dumper(\%records_for); #Get the name of the 2nd record with date '2007-05-26'; print $records_for{'2007-05-26'}[1]{'NAME'}, "\n"; #or, get the names of all records: foreach my $date (keys %records_for) { my $i = 0; foreach my $record (@{$records_for{$date}}) { print "$date($i): $record->{NAME}\n"; $i++; } } __DATA__ NAME,DATE,COLOR,SIZE Paul,2007-05-26,blue,large John,2007-04-21,red,small Mary,2007-05-26,orange,medium Peter,2006-01-30,blue,small Hope this helps, Paul Lalli -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
Hi, To access element of a given DATE (sat ... date_inp) from Hofdates you can do the following: my $date_inp = ... ; die "No etries for date $date_inp" unless (exists $Hofdates{$date_inp} and @{$Hofdates{$date_inp}}); foreach my $hash_ref (@{$Hofdates{$date_inp}}) { while (my ($field,$value) = each %$hash_ref) { print "Fieal = $field, value = $value\n"; } } Hope that helps Yaron Kahanovitch - Original Message - From: "pauld" <[EMAIL PROTECTED]> To: beginners@perl.org, [EMAIL PROTECTED] Sent: 14:17:57 (GMT+0200) Africa/Harare שבת 26 מאי 2007 Subject: accesing a hash of an array of hashes ive read a load of data in from a CSV file with Text::CSV and ended up with a hash (%hash) where the keys are the column labels. my @headings=split(/,/,$rows[0]) and then for (my $j=1;$j<$#rows;$j++) { my $status = $csv->parse ($rows[$j]); # parse a CSV string into fields my @columns = $csv->fields (); # get the parsed fields for (my $i=0;$i<$#columns;$i++) {$hash{$headings[$i]}=$columns[$i];} I want to process the data once its grouped by the date field present in $hash. So i think I want a hash of dates where the key is that date field I push onto the value the hashes of the records that contain the date push @{$Hofdates{$hash{DATE}}},\%hash; but im having a problem working out how to access the individual items in the hashes that are elements of the array -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
Hi, Be aware that you have a small problem. Your script includes: for (my $j=1;$j<$#rows;$j++) ... for (my $i=0;$i<$#columns;$i++) I think It should be for (my $j=1;$j<=$#rows;$j++) ... for (my $i=0;$i<=$#columns;$i++) Cheers Yaron Kahanovitch - Original Message - From: [EMAIL PROTECTED] To: "pauld" <[EMAIL PROTECTED]> Cc: "beginners" Sent: 19:47:38 (GMT+0200) Africa/Harare שבת 26 מאי 2007 Subject: Re: accesing a hash of an array of hashes Hi, To access element of a given DATE (sat ... date_inp) from Hofdates you can do the following: my $date_inp = ... ; die "No etries for date $date_inp" unless (exists $Hofdates{$date_inp} and @{$Hofdates{$date_inp}}); foreach my $hash_ref (@{$Hofdates{$date_inp}}) { while (my ($field,$value) = each %$hash_ref) { print "Fieal = $field, value = $value\n"; } } Hope that helps Yaron Kahanovitch - Original Message - From: "pauld" <[EMAIL PROTECTED]> To: beginners@perl.org, [EMAIL PROTECTED] Sent: 14:17:57 (GMT+0200) Africa/Harare שבת 26 מאי 2007 Subject: accesing a hash of an array of hashes ive read a load of data in from a CSV file with Text::CSV and ended up with a hash (%hash) where the keys are the column labels. my @headings=split(/,/,$rows[0]) and then for (my $j=1;$j<$#rows;$j++) { my $status = $csv->parse ($rows[$j]); # parse a CSV string into fields my @columns = $csv->fields (); # get the parsed fields for (my $i=0;$i<$#columns;$i++) {$hash{$headings[$i]}=$columns[$i];} I want to process the data once its grouped by the date field present in $hash. So i think I want a hash of dates where the key is that date field I push onto the value the hashes of the records that contain the date push @{$Hofdates{$hash{DATE}}},\%hash; but im having a problem working out how to access the individual items in the hashes that are elements of the array -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
On 05/26/2007 07:17 AM, pauld wrote: ive read a load of data in from a CSV file with Text::CSV and ended up with a hash (%hash) where the keys are the column labels. my @headings=split(/,/,$rows[0]) and then for (my $j=1;$j<$#rows;$j++) { my $status = $csv->parse ($rows[$j]); # parse a CSV string into fields You don't check $status to see if the parse succeeded. my @columns = $csv->fields (); # get the parsed fields for (my $i=0;$i<$#columns;$i++) {$hash{$headings[$i]}=$columns[$i];} Now %hash contains the data for the last record processed; however, data from any previous records have been obliterated. I want to process the data once its grouped by the date field present in $hash. So i think I want a hash of dates where the key is that date field I push onto the value the hashes of the records that contain the date push @{$Hofdates{$hash{DATE}}},\%hash; but im having a problem working out how to access the individual items in the hashes that are elements of the array The module Data::Dumper can help you see what's in your hash, but you need to rethink how you initialize the first hash (%hash). -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
On May 26, 1:51 pm, [EMAIL PROTECTED] (Mumia W.) wrote: > On 05/26/2007 07:17 AM, pauld wrote: > > > ive read a load of data in from a CSV file with Text::CSV and ended > > up with a hash (%hash) where the keys are the column labels. > > my @headings=split(/,/,$rows[0]) > > and then > > > for (my $j=1;$j<$#rows;$j++) > > { > > my $status = $csv->parse ($rows[$j]); # parse a CSV string into > > fields > > You don't check $status to see if the parse succeeded. > > > my @columns = $csv->fields (); # get the parsed fields > > > for (my $i=0;$i<$#columns;$i++) > > {$hash{$headings[$i]}=$columns[$i];} > > Now %hash contains the data for the last record processed; however, data > from any previous records have been obliterated. > > > I want to process the data once its grouped by the date field present > > in $hash. So i think I want a hash of dates where the key is that > > date field > > I push onto the value the hashes of the records that contain the date > > > push @{$Hofdates{$hash{DATE}}},\%hash; > > > but im having a problem working out how to access the individual > > items in the hashes that are elements of the array > > The module Data::Dumper can help you see what's in your hash, but you > need to rethink how you initialize the first hash (%hash). So long as the OP declares his %hash in the for loop, there's nothing wrong with how it's initialized. The OP did not show where he's declaring it, unfortunately. If he made the mistake of declaring it outside the for loop, then he's adding multiple copies of the same hash to the array, and that single hash is going to be repeatedly changed through the program. Paul Lalli -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
thanks for the help - im looking up hash slices - but id like to get something that works and then i can add new ideas etc so im going to leave it as it for the time being. Data::Dumper has helped sort out where an error is coming #!/usr/bin/perl -w use strict; use warnings; open O, "<$file" or die "could not open $file - $!"; undef $/; my $whole_file = ; close O; $whole_file=~s/\x0D\x0A1/\x0D\x0AABC1/g;my @rows=split(/\x0D\x0AABC/, $whole_file); ##splits in the correct place after looking at the CSV file with a hex editor - ugly but it seems to work ATM## my %hash; my @headings=split(/,/,$rows[0]) for (my $j=1;$j<=2;$j++) { my @columns = $csv->fields (); for (my $i=0;$i<=$#columns;$i++) {$hash{$headings[$i]}=$columns[$i];} print Dumper(%hash); push (@{$Hofdates{$hash{OPDATE}}},\%hash); print Dumper (%Hofdates); } and i get this output #1st record $VAR1 = 'STANTIME'; $VAR2 = '06:04'; $VAR3 = 'T3_AN2no'; $VAR4 = ''; $VAR5 = 'DESC3'; $VAR6 = ''; $VAR7 = 'T1_ANSNAME'; etc etc to the end then -01/10/2006---BROWN--- $VAR1 = '01/10/2006'; $VAR2 = [ { 'STANTIME' => '06:04', 'T3_AN2no' => '', 'DESC3' => '', 'T1_ANSNAME' => 'SMITH', 'P3_STANDTIME' => '', 'T2_AN2name' => '', 'CANCREASON' => '', 'RN2_NO' => '', 'T2_SUSDuty' => '' } ]; ###2nd record from file $VAR1 = 'STANTIME'; $VAR2 = '17:39'; $VAR3 = 'T3_AN2no'; $VAR4 = ''; $VAR5 = 'DESC3'; $VAR6 = ''; $VAR347 = 'CANCREASON'; $VAR348 = ''; $VAR349 = 'RN2_NO'; $VAR350 = ''; $VAR351 = 'T2_SUSDuty'; $VAR352 = ''; --01/10/2006---JONES-- $VAR1 = '01/10/2006'; $VAR2 = [ { 'STANTIME' => '17:39', 'T3_AN2no' => '', 'DESC3' => '', 'T1_ANSNAME' => '', 'P3_STANDTIME' => '', 'P4_OPCS4_3' => '', 'STANDATE' => '01/10/2006', 'CANCREASON' => '', 'RN2_NO' => '', 'T2_SUSDuty' => '' }, $VAR2->[0] ]; grenada tmp # so its pushing the second hash onto the array and overwriting the 1st -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
On May 27, 4:37 pm, [EMAIL PROTECTED] (Pauld) wrote: > thanks for the help - im looking up hash slices - perldoc perldata Entire arrays (and slices of arrays and hashes) are denoted by '@', which works much like the word "these" or "those" does in English, in that it indicates multiple values are expected. @days # ($days[0], $days[1],... $days[n]) @days[3,4,5]# same as ($days[3],$days[4],$days[5]) @days{'a','c'} # same as ($days{'a'},$days{'c'}) > but id like to get > something that works and then i can add new ideas etc so im going to > leave it as it for the time being. > > Data::Dumper has helped sort out where an error is coming > > #!/usr/bin/perl -w > use strict; > use warnings; > open O, "<$file" or die "could not open $file - $!"; > undef $/; > my $whole_file = ; > close O; > $whole_file=~s/\x0D\x0A1/\x0D\x0AABC1/g;my @rows=split(/\x0D\x0AABC/, > $whole_file); > ##splits in the correct place after looking at the CSV file with a > hex editor - ugly but it seems to work ATM## absolutely no idea what's making you think any of this is necessary. > my %hash; > my @headings=split(/,/,$rows[0]) > for (my $j=1;$j<=2;$j++) > { > my @columns = $csv->fields (); > > for (my $i=0;$i<=$#columns;$i++) {$hash{$headings[$i]}=$columns[$i];} > > print Dumper(%hash); > push (@{$Hofdates{$hash{OPDATE}}},\%hash); > print Dumper (%Hofdates); > > } > > so its pushing the second hash onto the array and overwriting the > 1st No kidding. Did you read my reply? That's exactly what I said would happen. Declare your hash in the smallest scope possible - inside the (first) for loop. That way, when each iteration of the for loop starts, you get a brand new hash rather than reusing the same one. If you don't understand what that means - move the 'my %hash;' line from where it is to just before the 'my @columns = $csv->fields ();' line. Paul Lalli -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: accesing a hash of an array of hashes
From: pauld <[EMAIL PROTECTED]> > ive read a load of data in from a CSV file with Text::CSV and ended > up with a hash (%hash) where the keys are the column labels. > my @headings=split(/,/,$rows[0]) > and then > > for (my $j=1;$j<$#rows;$j++) > { > my $status = $csv->parse ($rows[$j]); # parse a CSV string into > fields > my @columns = $csv->fields (); # get the parsed fields > > for (my $i=0;$i<$#columns;$i++) > {$hash{$headings[$i]}=$columns[$i];} > > I want to process the data once its grouped by the date field present > in $hash. Maybe your task would be easier if you used DBI and DBD::CSV and use SQL to group the data the way you need them instead of loading the raw data and "hand-processing" them. Jenda = [EMAIL PROTECTED] === http://Jenda.Krynicky.cz = When it comes to wine, women and song, wizards are allowed to get drunk and croon as much as they like. -- Terry Pratchett in Sourcery -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/