Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi
I'm having headaches with this.

What I want to do is to create some loop mechanism that allows me to iterate through an @array.
The starting position of the loop is calculated from $offset_value.

$offset_value will be between 0 and (scalar @array) -1

e.g

@array = (qw/ Fred Mark Joe Mary Paul /); $offset_value = 0
Then I would want get the following values returned
Fred Mark Joe Mary Paul
incrementing $offset then I want to get
Paul Fred Mark Joe Mary
Essentially the loop moves the last element to become the first.

What I have tried is the reverse of what I want :(
my @array=(qw/ Fred Mark Joe Mary Paul /); my $offset=0; my $loop=0; while ($loop < 10){ # loop is just to increment the offset value # main loop below for (my $i=0;$i<scalar @array;$i++){ my $r = $i + $offset; if ($r > scalar @array-1){ $r = $r - (scalar @array); } print @array[$r]; } $offset++; $offset=($offset>(scalar @array -1)?0:$offset; $loop++; }
Any Clues/hints/help much appreciated.
Regards
Mark K.

update (broquaint): tidied up formatting

Replies are listed 'Best First'.
Re: looping backwards
by eyepopslikeamosquito (Archbishop) on Jul 29, 2003 at 09:32 UTC

    The usual way to do a circular array is to use the % operator. For example, this will start from Joe (offset 2):

    my @array=qw/ Fred Mark Joe Mary Paul /; my $offset=2; for (0..$#array) { print $array[$offset++ % @array], "\n" }
      Thanks, I was thinking of using slices etc. but using % is an excellent solution - I would have never thought of it.

      Cheers Very much - ya deserve a pat on back.
      Regards
      Mark K
Re: looping backwards
by Abigail-II (Bishop) on Jul 29, 2003 at 13:45 UTC
    I'd use a slice:
    #!/usr/bin/perl use strict; use warnings; my @arr = qw /Fred Mark Joe Mary Paul/; local $, = " "; for (my $o = 0; $o < @arr; $o ++) { print "$o:", @arr [$#arr - $o + 1 .. $#arr, 0 .. $#arr - $o], "\n" +; } __END__ 0: Fred Mark Joe Mary Paul 1: Paul Fred Mark Joe Mary 2: Mary Paul Fred Mark Joe 3: Joe Mary Paul Fred Mark 4: Mark Joe Mary Paul Fred

    Abigail

      Very nice. Minor shortening to:

      @arr [@arr - $o .. $#arr, 0 .. $#arr - $o]

      Using the % trick, you might try this instead:

      @arr [map $_ % @arr, @arr - $o .. @arr - $o + $#arr] or: my $p = @arr - $o; @arr [map $p++ % @arr, @arr]

      So your slice looks a bit better.

Re: looping backwards
by RMGir (Prior) on Jul 29, 2003 at 09:20 UTC
    This is a clunky answer, but I think it will work...

    The idea is to use a negative slice to remove elements from the end of your list of indices, then unshift them onto the beginning...

    my @indices=0..$#array; # this is a NOP if $offset is 0, I think my @slice=splice @indices,-$offset; unshift @indices,@slice; foreach my $index(@indices) { # do whatever you want here print $array[$index]; }
    I _think_ that's what you want, is it?
    --
    Mike