[Cascavel-pm] Loop de dois em dois elementos

Luis Campos de Carvalho lechamps em terra.com.br
Quarta Outubro 22 09:43:10 CDT 2003


Nelson Ferraz wrote:
> Pessoal,
> 
> Aqui vai um probleminha interessante.
> 
> Eu tenho uma lista:
> 
>     @list = qw(q w e r t y);
> 
> Eu posso fazer um loop simples como este:
> 
>     for $el (@list) {
>       print "$el\n";
>     }
> 
> Mas imagine que eu queira fazer um loop de dois em dois elementos, 
> mantendo a ordem original da lista. A maneira mais natural seria algo 
> assim:
> 
>     for $el1, $el2 (@list) {
>       print "$el1 - $el2\n";
>     }
> 
> Mas este código não funciona.
> 
> Existem vários workarounds, como por exemplo:
> 
>     while (my ($el1, $el2) = splice(@list, 0, 2)) {
>       print "$el1 - $el2\n";
>     }
> 
> Curiosamente, este é um exemplo em que a linguagem Perl não simplifica a 
> nossa vida, tornando uma coisa simples mais difícil do que deveria ser.
> 
> Um caso tão raro que resolvi compartilhar com vocês! :)
> 
> (A propósito... tenho certeza de que muitos de vocês pensaram na 
> seguinte solução:
> 
>     my %hash = @list;
>     foreach (keys %hash) {
>       print "$_ - $hash{$_}\n";
>     }
> 
> Infelizmente, esta não seria uma solução válida, pois o hash não mantém 
> a ordem original da lista.)
> 

   Você pode usar um hack sujo

package ACME::List::CoupleInteractor;

use Exporter;
use base qw/ Exporter /;
our @EXPORT; our EXPORT_OK; our @ISA;

sub new{
   my $type = shift;
   my @data = @_;
   my $self = bless [], $type;

   # Garante um numero par de elementos sempre
   push @data, undef
     unless (scalar @_)%2!=0;
   push @{$self}, [shift, shift] while( @_ > 0 );
}

sub Interact{
   my $self = shift;
   my $code = shift;
   die 'Usage: $CoupleInteractor->Interact( $code_ref )';

   return map $code->( $_->[0], $_->[1] ), @{$self};
}

1;

package main;
use ACME::List::CoupleInteractor;

my @list = qw( q w e r t y );
my $ci = new ACME::List::CoupleInteractor( @list );
my $code_ref = sub {
   my ( $a, $b ) = ( shift, shift );
   print "A: $a, B: $b\n";
}

# Simples o suficiente para você?
$ci->Interact( $code_ref );
__END__
-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
   Luis Campos de Carvalho is Computer Scientist,
   PerlMonk [SiteDocClan], Cascavel-pm Moderator,
   Unix Sys Admin && Certified Oracle DBA
   http://br.geocities.com/monsieur_champs/
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=




Mais detalhes sobre a lista de discussão Cascavel-pm