John,
I am a lotus user so my top-down reply is default ...sorry.
I think all looks good, but I have to ask why are you initializing an array
to hold values of a hash with keys?
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;
My whole purpose was to populate a hash like so:
my %hash = {
F01000 => '0%',
F01001 => '10%',
F01002 => '100%',
};
If one cannot and should not push a hash, then what is the ideal way to
populate a hash..... like so?
for ( <FH>) {
for my $d (keys %HoA) {
print "$d: @{$HoA{$d} }\n";
}
}
OR
my %HoA = ();
for (<FH> ) {
$HoA{$i++} = (split)[-1]
}
????
thx again...derek
John Doe
<security.departm
[EMAIL PROTECTED]> To
[email protected]
05/03/2005 12:37 cc
AM
Subject
Re: populating a hash with % used
as the key and F string as the
value
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>
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>