I have a list of names:
@names = qw(John Peter Michael);
I want to take 2 values from it, so I get John and Peter. If I want to take 2 more - I get Michael and John. 1 more - Peter. 3 more - Michael John and Peter, and so on.
I've started writing a subroutine where a global index ID would be set and remembered, and would reset itself to zero once it reaches scalar limit of an array, but then I read somewhere that Perl arrays "remember" the position they were looped.
Is that true or am I misunderstanding something? Is there a way to do my task an easy way?
It's not that hard to roll your own iterator, but perlfaq4 has your need covered:
How do I handle circular lists?
(contributed by brian d foy)
If you want to cycle through an array endlessly, you can increment the index modulo the number of elements in the array:
my @array = qw( a b c ); my $i = 0; while( 1 ) { print $array[ $i++ % @array ], "\n"; last if $i > 20; }You can also use
Tie::Cycleto use a scalar that always has the next element of the circular array:use Tie::Cycle; tie my $cycle, 'Tie::Cycle', [ qw( FFFFFF 000000 FFFF00 ) ]; print $cycle; # FFFFFF print $cycle; # 000000 print $cycle; # FFFF00The
Array::Iterator::Circularcreates an iterator object for circular arrays:use Array::Iterator::Circular; my $color_iterator = Array::Iterator::Circular->new( qw(red green blue orange) ); foreach ( 1 .. 20 ) { print $color_iterator->next, "\n"; }
The subroutine is really quite simple (implemented as circularize in the code below). The value of $i is retained in $colors's scope, so no need for state variables:
sub circularize {
my @array = @_;
my $i = 0;
return sub { $array[ $i++ % @array ] }
}
my $colors = circularize( qw( red blue orange purple ) ); # Initialize
print $colors->(), "\n" for 1 .. 14; # Use
I never fully understood that mechanism (is it only on foreach?). I would just use state values, e.g.:
my @names = qw(John Peter Michael);
sub GetNames($) {
my $count = shift;
my @result = ();
state $index = 0;
state $length = scalar(@names);
while($count--) {
push(@result, $names[($index++ % $length)]);
}
return @result;
}
print join(", ", GetNames(2)), "\n\n";
print join(", ", GetNames(4)), "\n";
Outputs:
John, Peter
Michael, John, Peter, Michael
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With