Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

for, foreach, dereferencing hashes. 2

Status
Not open for further replies.

1DMF

Programmer
Jan 18, 2005
8,795
GB
Having stumbled acros a few errors over the week, I realised, it was because i had failed to understand how the FOR command compared to FOREACH worked on an array of hashes, this also brought to light the ways in which you can de-reference a hash.

So my question is which is better, which is faster or does it not matter.

for my examples my @array = "An array of hash references"

1st example
Code:
foreach my $hashref (@array){
   print $$hashref{'key1'};
}
2nd example
Code:
foreach my $hashref (@array){
   print $hashref->{'key1'};
}
3rd example
Code:
for(my $x=0; $x<=$#array; $x++){
   print $array[$x]{'key1'};
}

my understanding is that becasue PERL see's []{} it automatically de-references the hash.

is that better or quicker and is it ok to de-reference a hash using double $$, rather than ->.

is there a "standard" way of doing this or is it down to preference.

cheers,

1DMF

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
your second example of "foreach" looks better. Not sure if it is any faster than the first example though.

the "for" loop (IMHO) is horrible. There is no need to use the C style syntax with perl:

Code:
for (0 .. $#array) {
   print $array[$_]->{'key1'};
}
 
for (0 .. $#array) {
print $array[$_]->{'key1'};
}
That's valid PERL, cool, and now I see a use in $_ , thanks Kevin.

but you would still use the for each, does it matter about leaving out ->, i take it i still need $$ to dereference?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
in the "foreach" you have to use the -> if you don't use $$. In the for loop, I don't think the -> is actually not necessary but I used it for clarity.
 
but is $$ bad ?
is -> "the proper way"

you see i've been bitten by doing things because they work, to find out it was bad syntax and worked by chance.

and on your example of the non c+ style for loop
Code:
for (0 .. $#array){}
if you did
Code:
for ($#array .. 0){}

does it infer step -1


"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
.. is perl's range operator, so what better place than perlop to read about it?

Be wary of using 0 .. $#array when @array is huge. You're better off saying something like this, unless you're using the numeric index as something other than retrieving that one element:
Code:
[COLOR=#0000FF]for[/color] (@array) {
   [COLOR=#FF0000]print[/color] $_->{[COLOR=#808080]'key1'[/color]};
}

And one last tidbit, the following two lines are equivilent, as an -> is implied between sets of [] or {}.
Code:
[COLOR=#FF0000]print[/color] $array[ignore][[/ignore]$_]->{[COLOR=#808080]'key1'[/color]};
[COLOR=#FF0000]print[/color] $array[ignore][[/ignore]$_]{[COLOR=#808080]'key1'[/color]};
so IMO you're better off with brevity and leaving it out.

Alright, one more thing. I tend to prefer -> over $$ because it expands another level deeper without changing syntax.
Code:
[COLOR=#FF0000]print[/color] $hashref->{[COLOR=#808080]'key1'[/color]};
[COLOR=#FF0000]print[/color] $$hashref{[COLOR=#808080]'key1'[/color]}; [COLOR=#006600]#same[/color]
[COLOR=#FF0000]print[/color] $hashref->{[COLOR=#808080]'key1'[/color]}{[COLOR=#808080]'lvl2'[/color]}; [COLOR=#006600]#works[/color]
[COLOR=#FF0000]print[/color] $$hashref{[COLOR=#808080]'key1'[/color]}{[COLOR=#808080]'lvl2'[/color]}; [COLOR=#006600]#fails[/color]

- Andrew
Text::Highlight - A language-neutral syntax highlighting module in Perl
also on SourceForge including demo
 
Forgive me, my head's not in Perl anymore these days, that last one works fine. :cool:

I have a vauge memory of there being some reason I used -> over $$ but that's apparently not it.

- Andrew
Text::Highlight - A language-neutral syntax highlighting module in Perl
also on SourceForge including demo
 
icrf - Thanks for the heads up over
for( x .. $#array){}
it also gives me further insight into the $_ variable. Your example ...
Code:
for(@array){print $_->{'key'};}
looks like a quicker foreach (well in code), but Kevan advised to use A foreach OVER a for loop.

this is where i get confused over the correct syntax to use in my script.

for vs foreach - that is the question!

i like to use $#array and [0] is always undefined, so $#array = record count.

but having [0] undefined, creates problems when using foreach or for(@array).

So how many records (array of hashes) is too many to be using
Code:
for( 1 .. $#array){print $array[$_]{'key'};}


"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
really, you should use @array as your record count, $#array is the index of the last item in the array. If you use @array in scalar context ("if @array > 20" "$count = @array" "scalar @array" etc) you get the number of records in the array. Much cleaner, I think, b/c $#array is hard for me to type.

And to the for/foreach debate, I'm not entirely sure there's any difference. You can say "for my $value (@array)" if you'd like. The shortcut to not specifying the ... iterator?and just having it default to $_ doesn't work well when you nest for loops, b/c it keeps getting re-aliased. I generally name the outside loops and use $_ (if applicable) in the inner loop. Many of perl's functions use $_, so it's best to only use it within short scope so you can keep track.

- Andrew
Text::Highlight - A language-neutral syntax highlighting module in Perl
also on SourceForge including demo
 
damn it, if only i'd know @array in a scalar context = record count.

so your saying...

Code:
my @array = ('a' .. 'z');
for(@array){
   print "$_\n";
}
print "There are " . @array . " letters.";

is the quickest and shortest, syntax acceptable notation

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
for and foreach are the same thing.
The foreach keyword is actually a synonym for the for keyword, so you can use foreach for readability or for for brevity. (Or because the Bourne shell is more familiar to you than csh, so writing for comes more naturally.)
See the docs here for more info.
 
perl usually can tell when you want to use @array in list context or in scalar context.

If you do this:

if (@array > 20)

perl will know what to do since it's clear. > is a numeric operator so @array will be treated in scalar context.

This is perl 101:

$n = @array;

I would have assumed you already knew that. I don't mean that to sound condescending, it's just that it is so basic I would have felt sure you would already know that.

I am not sure what the concern is with (0 .. $#array) if the array is huge, maybe icrf will elaborate on that and give a general idea of what huge is.

Generally I try and use:

for (@array) {

whenever possible. It's personal preference but to me it's short and concise and clear.
 
I'm sorry, from reading perlop it includes a warning about Perl making a temporary array when using the range operator, so using it for a huge array of numbers would needlessly consume memory. However, I either read over the "...older versions of Perl might burn a lot of memory..." part, or actually remember reading that when Perl was older, not sure.

In short, there should be no harm in doing it now.

- Andrew
Text::Highlight - A language-neutral syntax highlighting module in Perl
also on SourceForge including demo
 
if you did
Code:
for ($#array .. 0){}
does it infer step -1

No it doesn't. You can do this however:

Code:
for (reverse (0 .. $#array)) {}




 
icrf,

no apology necessary mate. I'm always gald to get advice/comments/opinions/concerns since I know my perl knowledge has some large gaps in it.
 
thanks for all you help guys, things are much clearer now and Kevin
This is perl 101:

$n = @array;

I would have assumed you already knew that. I don't mean that to sound condescending, it's just that it is so basic I would have felt sure you would already know that.

never assume anything, I knew $#array was the last index and @array was an array, not @array in the right context became record count.

But you can assume that from now on :)

P.S. what does PERL 101 mean?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
perl 101 means:

beginner class in perl

in the states 101 is often used to signify the begining/introductory class of something:

Biology 101
Chemistry 101
etc
etc
etc
 
Kevin, I enjoy giving correct advice, but I hate speaking blatant mistruths and always feel bad when I let them slip.

1DMF, it may be worth a puruse of perldata to see if there's any other little perl basics that has slipped by. The bundled documentation has often been criticized for not being new-programmer friendly, but if you've been programming for a little while, it's a great reference on the language. Check your local perldoc source for perldsc, perlref, and perlreftut, too, they all contain good info on references and data structures.

- Andrew
Text::Highlight - A language-neutral syntax highlighting module in Perl
also on SourceForge including demo
 
i find most of the perldocs not beginner friendly.

Infact i find them completely written in another language from the planet WTF.

but i keep hammering away, with the help of you nice people. thanks for all the help.



"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top