Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: compare arrays numbers

by ikegami (Patriarch)
on Feb 16, 2010 at 18:52 UTC ( [id://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 :)

Replies are listed 'Best First'.
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
Domain Nodelet?
Node Status?
node history
Node Type: note [id://823529]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-03-29 01:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found