Re: array looping with foreach
by Roy Johnson (Monsignor) on Jan 18, 2008 at 16:20 UTC
|
See this subthread about each for arrays (and my relatively trivial implementation).
The ways you've listed are pretty standard for using for, with the second being somewhat preferred, IMO.
Update: if you use method #1, put the increment in a continue block.
Caution: Contents may have been coded under pressure.
| [reply] [d/l] [select] |
Re: array looping with foreach
by amarquis (Curate) on Jan 18, 2008 at 16:25 UTC
|
Both look fine to me, although I think I'd personally lean away from option 1. I like to have as few moving parts as possible, and an index that can potentially de-sync if I throw in loop control constructs (and not hit the increment) worries me. But, I'm bad, so many things worry me.
I was curious to see what I've done in the past, so I took a peek at the script I've been working on this week. Interestingly, I think that this problem of "Tracking the index and the value concurrently" is a "C problem" in my mind. Each place I've had to do it, I've rolled a C-style for loop :).
| [reply] |
Re: array looping with foreach (try Array::Each::Override)
by grinder (Bishop) on Jan 18, 2008 at 17:07 UTC
|
You can install Array::Each::Override and override each. This will allow you to obtain both the index and the value of each array element.
• another intruder with the mooring in the heart of the Perl
| [reply] |
|
|
I'm a little confused by the point of Array::Each::Override
Being able to override each to use it on an array is nice and surely useful at times. But at the same time you're hurting the built in each performance on hashes (which you're likely to be doing more of in your code to start with). The values override adds nothing to working with arrays, and again hurts the built in values performance on hashes. The keys override doesn't appear to add much in the way of usefulness either again with the built in keys performance hit.
But I'm running off topic...
| [reply] |
Re: array looping with foreach
by NetWallah (Canon) on Jan 18, 2008 at 19:03 UTC
|
Depending on how often you need to use this construct, you could build your own iterator with callback, to handle this:
my @arr = ( 110..117) ;
# Generic array Iterator ---
# Calls back $cb passing it a 2-element array : the INDEX, and an alia
+s to the contents at that index
sub iter{
my ($cb,$aref)=@_; # $cb is the callback sub ref passed in..
my $idx=0;
for(@$aref){
$cb->($idx,$_);
$idx++
}
};
# Call the iterator
iter(sub{print "ops : @_\n"},\@arr);
# Prints:
#ops : 0 110
#ops : 1 111
#ops : 2 112
# ....etc ...
Advantages:
- Index is localized/encapsulated (and can be hardened, if necessary)
- No temporary arrays created (Memory efficient)
- CPU - Efficient (minimal overhead)
- Update 1:No initialization required, No overlap or threading issues(As compared to other implementations of the "each" function)
"As you get older three things happen. The first is your memory goes, and I can't remember the other two... "
- Sir Norman Wisdom
| [reply] [d/l] |
Re: array looping with foreach
by ikegami (Patriarch) on Jan 18, 2008 at 19:48 UTC
|
The following both provides the index and makes $ele an alias to the array element as if you had done for my $ele (@array):
for my $idx (0..$#array) {
for my $ele ($array[$idx]) {
...
}
}
| [reply] [d/l] [select] |
Re: array looping with foreach
by jeanluca (Deacon) on Jan 18, 2008 at 16:54 UTC
|
You examples look fine to me too, but if you really want to do it differently, this seems to work too
#!/usr/bin/perl -l
use strict;
use warnings;
my @arr = ( 1,2,3,4,5) ;
my $n = 1 ;
my @new = map{ $n = 1000; ++$_ } @arr ;
print "new=@new";
print "n=$n\n";
Cheers LuCa | [reply] [d/l] |
Re: array looping with foreach
by mpeg4codec (Pilgrim) on Jan 18, 2008 at 22:54 UTC
|
Why not use the traditional C-style version of for as amarquis hinted?
for (my $i = 0; $i < @array; ++$i) {
# do something with $array[$i]
# do something with $i
}
| [reply] [d/l] |
|
|
for my $index (0 .. $#array) {
...
}
There are situations where a C style for loop is appropriate in Perl, but they are in fact fairly rare. About the only case that readily comes to mind is where a complicated termination test is required, and even then it is often clearer to use last with a statement modifier in the body of the loop. If multiple statements need to be executed at the end of each iteration you should use a continue block rather than pile all the statements into the iteration part of a C for loop header.
Perl is environmentally friendly - it saves trees
| [reply] [d/l] |
|
|
It's fun to see all the variations (map/module/each/iter) but in my mind, the C-Style loop wins (mpeg4codec++). I've always used this construction, maybe it's just because I learned C long before Perl, but it's a clear and well known construction that doesn't create extra arrays, use Module.pm, or have the (probably trivial) function call overhead of iterators. I wonder if we don't occasionally try to be too Perlish just because this is NOT C.
| [reply] |
|
|
I wonder if we don't occasionally try to be too Perlish just because this is NOT C.
I thought that was the point! We try to be Perlish because this isn't language X. Perhaps our definitions of "Perlish" differ.
Familiarity is not a good argument as not everyone comes from C. I suspect people who came from say a lisp or python background would not immediately recognize a C style for loop.
I will admit it is likely the most efficient, but, for me, that time is lost in correcting all my stupid off by one errors. | [reply] |
|
|