Am Dienstag, 3. Mai 2005 03.30 schrieb [EMAIL PROTECTED]:
> > * If the format of all your data lines is "consistent", you could use
>
> split
>
> > on \s+ to get the data fields instead of a tr/m cascade.
> >
> > * Then, if I understand you correctly, you wantto build a hash with %
>
> keys
>
> > and F... values. This could be done with code like
> >
> > push @{$lookup_hash{$pct_value}}, $F_value;
> >
> > eventually, you even want a 2nd level hash with the F field number as
>
> key,
>
> > if the F values are unique over the whole file and the last field alway
> > begins with an F.
>
> === test5.pl ===
> #!/usr/bin/perl
>
> use warnings; use strict;
>
> my @lines=split "\n", <<EOF;
> 1     2005/01/20 15:39   17   2%  -il-o-b-----  sg F01000
> 2     2005/01/20 15:53   14   1%  -il-o-b-----  sg F01001
> 3     2005/01/18 09:53    2   0%  -il-o-b-----  sg F01002
> 4     2005/02/04 16:41  196 100%  -il-o-b----f  sg F01003
> 5     2005/02/05 21:13  305 100%  -il-o-b----f  sg F01004
> EOF
>
> my %lookup;
> foreach (@lines) {
>         my @fields=split /\s+/;
>         push @{$lookup{$fields[4]}}, $fields[7];
> }
>
> print join "\n", map {$_.": ".(join ", ", @{$lookup{$_}})} sort {$a <=> $b}
>
> keys %lookup;
> print "\n";
> === end test5 pl ===
>
> This prints:
>
> 0%: F01002
> 1%: F01001
> 2%: F01000
> 100%: F01003, F01004
>
> ++++++++++++++++++++++++++++++++
>
> ok thank you, but a few questions:
>
> 1) In programming Perl, it states one cannot push or pop a hash on page 10
> paragraph 2.  "You cannot push or pop a has b/c it does not make sense; a
> hash has no beginning nor end."  

True :-)

> Why does Oreilly's PP 3rd edition say this?  

Hm... because its true :-))

> It looks like you are pushing data elements from @lines into 
> %lookup, correct?

(Please bear with my english while I try to explain...)

The data structure built in the foreach loop looks like 

my %lookup=(
 key1 => 
  ['val1a', 'val1b'] # etc. - note A
 key2 => 
  ['val2a', 'val2b'] # etc. - note B
)

This means that key1 and key2 are (ordinary) hash keys, and the lines 
commented with "note A/B" are (nearly ordinary) scalar values: The scalars 
are not "123" or "string", but arrayrefs (which are, like all refs, scalar 
values).

The push is done at the end of these _dereferenced_ arrayrefs (read: the 
arrays). These arrays are initialized automagically at the time of the first 
push to them.

The dereferencing is done by the '@{}' in

 push @{   $lookup{$fields[4]}   }, 
 $fields[7];

while 
 $lookup{$fields[4]} 

itself is the reference to the array (read: an arrayref).


> 2)  Is this :  print join "\n", map {$_.": ".(join ", ", @{$lookup{$_}})}
> sort {$a <=> $b}
>
>      stating
>
> for every $_ construct or default variable, 

No, you did not cite the part "keys %lookup;"


> join newline to a  
> map of  :  any character with a comma then space then the data elements
> from $lookup
>      sorted.

I add some formatting to explain. It's best understood if read backwards, from 
"keys %lookup" to "print"; imagine the execution flow in this direction:

print join "\n", 
   map {
      $_   .
      ": "   .
      (   join ", ", @{$lookup{$_}}   )
   }
   sort {$a <=> $b}
   keys %lookup;

"Take the keys from %lookup into $_, then sort $_ numerically, then use a 
map{} to format a string of every single hash key (in $_) and the 
corresponding array elements accessed via the 'scalar arrayref hash 
value' (again, @{} dereferences the arrayref). The map results in a string 
for every $_. These are concatenated by a newline and printed.

This could be written the long way (but now to be read topdown):

my @keys=keys %lookup;
my @sorted_keys=sort {$a <=> $b} @keys;
my @per_key_strings;
foreach my $k (@sorted_keys) {
 push @per_key_strings, 
  $k . ": " .  (   join ", ", @{$lookup{$_}}   );
}
print join "\n", @per_key_strings;


> 3) I know I can populate an array like so: 
> my (@array, $i )  = (); 

 my (@array, $i); 

or, for clarity:

 my @array; # no need to initialize with ()
 my $i=0; # explicitly state start value

> foreach  
> (<FH>) { $array[$i++] }

What's the sense of it since you don't assign any array element?

>      As an example, is it incorrect to do likewise to a hash as so:
>             my %HoA = ();
>             for (<FH> ) {
>                   $HoA{$i++} = (split)[-1]
>                }

Looks correct to me. If I wanted to be shure, I would run the code and then 
inspect the resulting data structure :-)

But, as somebody else already mentioned, it makes not much sense to use a hash 
with keys from 0..n, this could be done with an array containing elements 
0..n.

> 4)  for my $d (keys %HoA) {
>          print "$d: @{$HoA{$d} }\n";

Maybe the @{} here confuses in combination with above @{} that was used to 
"intentionally" dereference a scalar arrayref.

Here, @{} is a common way to interpolate one or more data elements into a 
string - also by dereferencing an arrayref which is formed by the value(s) - 
in most cases just one - within the @{}.

>       }
>
>      This was from copied from programming perl and strict did not complain
> and prints out the hash values.  Is there a better way?

I don't think so. But there are other ways to do it, for instance, avoiding 
@{}, 

 print "$d: ", $HoA{$d}, "\n";
 


I must admit that I had big problems with the english, maybe I missed the 
overview of your question(s),  but hope it was understandable.

joe.

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to