Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: compare arrays numbers

by ikegami (Pope)
on Feb 16, 2010 at 18:52 UTC ( #823529=note: print w/ replies, xml ) Need Help??


in reply to compare arrays numbers

To do something to each element of an array, you need a loop over each element of the array. I don't know what's special about for loops that they need to be avoided. Maybe if you told us that, we could help you better.

I wouldn't use a for loop anyway. I'd use a counting loop. The syntax of a counting loop is much simpler than that of a for loop, it's faster do to the much smaller number of opcodes, and it also uses a constant amount of memory. (Mostly for the first reason. The other two are bonuses.)

Counting loop (an optimised form of foreach loop):

$a[$_] -= $b[$_] for 0..$#a;

Foreach loop:

$a[$_] -= $b[$_] for (),0..$#a;

Using map like a foreach loop:

map { $a[$_] -= $b[$_] } 0..$#a;
while loop:
my $i = @a; $a[$i] -= $b[$i] while $i--;

Goto loop:

my $i = @a; goto CHECK; BODY: $a[$i] -= $b[$i]; CHECK: goto BODY if $i--;

Recursion loop:

sub subarray { my ($a, $b) = @_; local *_helper = sub { my $i = $_[0]; return if !$i--; $a->[$i] -= $b->[$i]; _helper($i); }; _helper(0+@$a); } subarray(\@a, \@b);

Recursion loop, take 2:

sub subarray { my ($a, $b) = @_; local *_helper = sub { return if !@_; $_[0] -= $_[-1]; shift; pop; &_helper; }; _helper(@$a, reverse(@$b)); } subarray(\@a, \@b);

pairwise loop:

use List::MoreUtils qw( pairwise ); @a = pairwise { $a - $b } @a, @b;

Update: Added more alternatives :)


Comment on Re: compare arrays numbers
Select or Download Code
Re^2: compare arrays numbers
by crashtest (Curate) on Feb 16, 2010 at 19:11 UTC

    You seem to be editing your post continuously, I hope by the time I submit this the snippet in question won't be outdated... although you seem to be adding to your examples, not modifying (apparently you're working on 1,001 ways to write a loop)

    In example #2:

    $a[$_] -= $b[$_] for (),0..$#a; # ^-- ... why?
    What is up with the stray ()? Just a typo, or are you doing something else here (I thought you might be somehow forcing list context, but 0..$#a is a list anyway).

    Without the spare empty list, the expression evaluates equivalently in my perl (5.10.0).

      $a[$_] -= $b[$_] for 0..$#a;
      is optimised into a counting loop (O(1) memory).
      $a[$_] -= $b[$_] for (),0..$#a;
      is not optimised (O(N) memory).

      but 0..$#a is a list anyway

      ".." is usually the range operator, but not in the first example. In fact, it's not an operator at all there. It's just a separator like the semicolons in for(;;).

      $ perl -MO=Concise,-exec -e'1 for (),$x..$y' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v:{ 3 <;> nextstate(main 1 -e:1) v:{ 4 <0> pushmark sM 5 <|> range(other->6)[t3] lK/1 \ 6 <#> gvsv[*y] s | 7 <1> flop lKM | Range op called goto 8 | to produce a list. f <#> gvsv[*x] s | g <1> flip[t4] lK / 8 <#> gv[*_] s 9 <{> enteriter(next->a last->d redo->a) lK/8 b <0> iter s c <|> and(other->a) vK/1 a <0> unstack v goto b d <2> leaveloop vK/2 e <@> leave[1 ref] vKP/REFC -e syntax OK $ perl -MO=Concise,-exec -e'1 for $x..$y' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v:{ 3 <;> nextstate(main 1 -e:1) v:{ 4 <0> pushmark s 5 <#> gvsv[*x] s \ Args for enteriter/S 6 <#> gvsv[*y] s / 7 <#> gv[*_] s 8 <{> enteriter(next->9 last->c redo->9) lKS/8 a <0> iter s b <|> and(other->9) vK/1 9 <0> unstack v goto a c <2> leaveloop vK/2 d <@> leave[1 ref] vKP/REFC -e syntax OK

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://823529]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2015-07-04 23:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (60 votes), past polls