burnt_ice091 <

burnt_ice091@...> wrote:

: What happens to the data that perl 'returns' when you pop or shift?

: I've tried "pop @array => $variable;", but this does not work (should

it?.....).

No.

: I've also tried ->, but that doesn't work either (damn OOP...).

perl functions are not generally OO.

: ANYWAY, how would you call this data back?

: I would like to pop the first element and then push it to the end.

Sounds like rotate in assembler. perlfunc describes most of the buitin

perl funcions.

my $popped = pop @array;

my $shifted = shift @array;

But to just rotate the array to the right or to the left,

you don't need to pop or shift. You could use an array

slice. You may be familiar with a slice already. Here's a

quick reminder. A slice is more than one element:

my @array = ( 0 .. 9 );

$array[0]; # first element of the array

@array[4 ..9] # last 6 elements - an array slice !

In the array above we could do a rotate with a more complex slice:

my @array = ( 0 .. 9 );

@array = @array[ 1 .. 9, 0 ]; # rotate array to the left

@array = @array[ 9, 0 .. 8 ]; # rotate array to the right

But what if we don't know the length of the array?

perl describes the last element of @array with $#array. We

can create a general case with:

@array = @array[ 1 .. $#array, 0 ]; # rotate array to the left

@array = @array[ $#array, 0 .. $#array - 1 ]; # rotate array to the right

Here are two subroutines I wrote to do this with any number of

rotations. It defaults to one rotation as above.

sub rotate_left {

my( $arr_ref, $rotations ) = @_;

$rotations ||= 1; # default to 1

return [ @$arr_ref[ $rotations .. $#$arr_ref, 0 .. $rotations - 1 ] ];

}

sub rotate_right {

my( $arr_ref, $rotations ) = @_;

$rotations ||= 1; # default to 1

$rotations = @$arr_ref - $rotations;

return [ @$arr_ref[ $rotations .. $#$arr_ref, 0 .. $rotations - 1 ] ];

}

These accept and return array references to increase speed.

We could also create routines that operate on the array in-place

and return the value of the shift (or pop). Here we do it with

rotate_left. With one rotation it returns a scalar. On a multiple

rotation it returns an array reference to the values that were

moved.

sub rotate_left {

my( $arr_ref, $rotations ) = @_;

$rotations ||= 1; # default to 1

@$arr_ref = @$arr_ref[ $rotations .. $#$arr_ref, 0 .. $rotations - 1 ];

return $$arr_ref[-1] if $rotations == 1;

return [ @$arr_ref[ -$rotations .. -1 ] ];

}

Here's what I tested with:

use strict;

use warnings;

use Data::Dumper;

my @array = ( 1 .. 10 );

print Dumper \@array;

print Dumper rotate_left(\@array, 4);

print Dumper \@array;

sub rotate_left {

my( $arr_ref, $rotations ) = @_;

$rotations ||= 1; # default to 1

@$arr_ref = @$arr_ref[ $rotations .. $#$arr_ref, 0 .. $rotations - 1 ];

return $$arr_ref[-1] if $rotations == 1;

return [ @$arr_ref[ -$rotations .. -1 ] ];

}

__END__

HTH,

Charles K. Clarkson

--

Head Bottle Washer,

Clarkson Energy Homes, Inc.

Small commercial and residential rehabilitation specialists.

254 968-8328

CJ Web Work - Solutions for Real Estate Investors.

972 216-4952