Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Loops in Perl

by carlriz (Beadle)
on Mar 11, 2014 at 18:26 UTC ( #1077883=perlquestion: print w/ replies, xml ) Need Help??
carlriz has asked for the wisdom of the Perl Monks concerning the following question:

I was looking at this expression in perl:

@ranks[@sorted_positions] = (0 .. $#sorted_positions);
Does perl increment the index for both arrays automatically? Is it shorthand for a 'foreach' loop?

Comment on Loops in Perl
Download Code
Replies are listed 'Best First'.
Re: Loops in Perl
by LanX (Canon) on Mar 11, 2014 at 18:52 UTC
    that's a list assignment to an array slice on the LHS.

    > Is it shorthand for a foreach loop?

    ehm ... well the effect is analogous to many scalar assignments

    $ranks[ $sorted_positions[$_] ] = $_ for 0 .. $#sorted_positions

    but actually it's an assignment of list to list

    > Does perl increment the index for both arrays automatically?

    there is no increment after the range operator created a list on the RHS.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: Loops in Perl
by kcott (Abbot) on Mar 11, 2014 at 21:12 UTC

    G'day carlriz,

    Let's say @sorted_positions has five elements (1, 3, 5, 7, 9). (So, $#sorted_positions will be 4.)

    The code you posted:

    @ranks[@sorted_positions] = (0 .. $#sorted_positions);

    will be evaluated like this:

    @ranks[1, 3, 5, 7, 9] = (0, 1, 2, 3, 4);

    The element $ranks[1] will be set to 0, the element $ranks[3] will be set to 1 and so on.

    Here's a short piece of code demonstrating this.

    #!/usr/bin/env perl -l use strict; use warnings; my @ranks = qw{a b c d e f g h i j}; my @sorted_positions = (1, 3, 5, 7, 9); print "@ranks"; @ranks[@sorted_positions] = (0 .. $#sorted_positions); print "@ranks";

    Output:

    a b c d e f g h i j a 0 c 1 e 2 g 3 i 4

    The elements with indices 0, 2, 4, 6 and 8 are unchanged. The remaining elements (with indices 1, 3, 5, 7 and 9) are set to the values 0, 1, 2, 3 and 4 respectively.

    -- Ken

      Awesome example. Thanks!

Re: Loops in Perl
by Laurent_R (Monsignor) on Mar 11, 2014 at 18:57 UTC

    Yes, what you see on the left side of the equal sign is called an array slice. You can do something like this:

    my @array = 0..5; my @ranks[@array] = 5..10; # @ranks now contains 5, 6, 7, 8, 9, 10
    The code you posted is just the same idea.

    Update:

    As noted by AnomalousMonk in the post just below, there is an error in the code above: it should be:
    my @array = 0..5; my @ranks; @ranks[@array] = 5..10; # @ranks now contains 5, 6, 7, 8, 9, 10
    We can't use "my" on an array with subscripts accessing to part of the array, the array must be declared before. I tested the code directly under the debugger, where it is not pôssible to use "my", and added the my on the line afterwards, creating erroneous code.

      my @ranks[@array] = 5..10; is a syntax error.

      c:\@Work\Perl>perl -wMstrict -MData::Dump -le "my @array = 0..5; my @ranks; @ranks[@array] = 5..10; dd \@ranks; " [5 .. 10]

      Update: However, the following works for initializing a new lexical (reverse used just to add some variety):

      c:\@Work\Perl>perl -wMstrict -MData::Dump -le "my @array = reverse 0 .. 5; my @ranks = (5 .. 10)[@array]; dd \@ranks; " [10, 9, 8, 7, 6, 5]
        Thank you for your comment, AnomalousMonk, you are right. I added the "my" after having tested and that was a mistake. I have updated my post accordingly.
Re: Loops in Perl
by Anonymous Monk on Mar 11, 2014 at 20:39 UTC
Re: Loops in Perl
by 2teez (Priest) on Mar 11, 2014 at 20:46 UTC

    Hi carlriz,
    Also check Slices Just a "kobo" note!

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: Loops in Perl
by Marshall (Prior) on Mar 14, 2014 at 05:14 UTC
    This is actually a rather strange idea in Perl.
    And I figure syntactically incorrect.

    Normal would be:

    @ranks= sort { my ($A) = (split($a,'')))[0]; my ($B) = split($b,'')))[0]; $A[0] <=> $B[0] }@ranks; #sorts on numeric comparison #between item's [0] in the @ranks array }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1077883]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (9)
As of 2015-07-30 23:48 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 (273 votes), past polls