Fabiano Reese Righetti

Técnicas de manipulação
Publicado em 19/08/2006

r2 - 19 Aug 2006 - JoenioCosta

Técnicas de manipulação

Este artigo aborda algumas técnicas de como manipular corretamente as estruturas um tanto complexas que perl permite criar, buscando explanar o máximo de detalhes possíveis.

Com um simples array pode-se interpretar várias estruturas de dados como uma fila, lista, arvores... Assim o trabalho fica muito mais simples e conseqüentemente mais rápido de se resolver.

Por se tratar de um assunto muito requisitado, ou seja, de extrema necessidade para quem deseja iniciar a programar, ele não vai ser muito teórico e sim exemplificativo.

1. Arrays

Mais conhecido como "vetor" ou ainda "matriz" (quando formado por duas ou mais dimensões) sendo basicamente formado por uma lista de elementos escalares e identificado pelo símbolo "@".

Array: "Uma seqüência ordenada de valores, armazenados de modo que você possa facilmente acessar qualquer um dos valores usando subscrito inteiro que especifica o offset do valor da seqüência". (Programação Perl, Ed. 3, pág. 1002)

Como descrito acima, todo array é acessado por um offset inteiro (começando pelo 0). O interessante disto é que pode usar números negativos também, obtendo-se um efeito "reverso" (de trás para frente).

Vamos supor que você queira acessar o último elemento, você poderia fazer assim:

   $array[$#array];

Como visto "$#" indica o número de elementos que existe no array. Mas simplificando, bastaria fazer isto.

   $array[-1];

1.1. Criando

Vou abordar como criar arrays "unidimensionais", "bidimensionais" e "tridimensionais". Perceba como é atribuído os valores por () e [] pois existe uma diferença entre eles. Existem vários métodos de se criar um array, isto vai depender de sua "criatividade", mas dentre estes métodos vou utilizar a função qw//.

     () - Significa que você esta atribuindo uma lista.
     [] - É uma referência aos escalares.
   qw// - Vai "quebrar" entre os espaços.
     .. - É uma seqüência de valores.







   # Unidimensional.
   my       @uni = ("Primeiro", "Segundo", "Terceiro", "Quarto");
   my @intervalo = ( 1 .. 50 );
   my    @quoted = qw(Primeiro Segundo Terceiro Quarto);
   my     @misto = (50, 5.1252351, "Numero");







   # Bidimensional.
   my        @bi = (
                    ["Primeiro", "Segundo", "Terceiro", "Quarto"],
                    [ 1 .. 50 ],
                    [ qw(Primeiro Segundo Terceiro Quarto) ],
                    [50, 5.1252351, "Numero"],
                   );







   # Tridimensional.
   my       @tri = (
                    [
                     ["Primeiro", "Segundo", "Terceiro", "Quarto"],
                     [ 1 .. 50 ],
                     [ qw(Primeiro Segundo Terceiro Quarto) ],
                     [50, 5.1252351, "Numero"],
                    ],
                    [
                     ["Primeiro", "Segundo", "Terceiro", "Quarto"],
                     [ 1 .. 50 ],
                     [ qw(Primeiro Segundo Terceiro Quarto) ],
                     [50, 5.1252351, "Numero"],
                    ],
                    [
                     ["Primeiro", "Segundo", "Terceiro", "Quarto"],
                     [ 1 .. 50 ],
                     [ qw(Primeiro Segundo Terceiro Quarto) ],
                     [50, 5.1252351, "Numero"],
                    ],
                   );

1.2. Acessando

O acesso a valores do array é feito por um número inteiro podendo ser positivo ou negativo.

   $# - Retorna o total de elementos que pertence ao array.




   # Unidimensional.
   $uni[0];  # Acessando um elemento.
   $uni[-1]; # Acessando o ultimo elemento.

   for my $x (0..$#uni) { # Imprimindo todos os elementos.
    print "\$uni[$x] == \"$uni[$x]\"\n";
   }







   # Bidimensional.
   $bi[0][0];   # Acessando um elemento.
   $bi[-1][-1]; # Acessando o último elemento.

   for my $x (0..$#bi) { # Imprimindo todos os elementos.
    for my $y (0..$#{$bi[$x]}) {
     print "\$bi[$x][$y] == \"$bi[$x][$y]\"\n";
    }
   }







   # Tridimensional.
   $tri[0][0][0];    # Acessando um elemento.
   $tri[-1][-1][-1]; # Acessando o último elemento.

   for my $x (0..$#tri) { # Imprimindo todos os elementos.
    for my $y (0..$#{$tri[$x]}) {
     for my $z (0..$#{$tri[$x][$y]}) {
      print "\$tri[$x][$y][$z] == \"$tri[$x][$y][$z]\"\n";
     }
    }
   }

1.3. Adicionando e Removendo

Com este simples array podemos facilmente interpretar estruturas como listas e filas apenas usando algumas funções que perl nos disponibiliza, entre elas:

   unshift() - Adiciona no início.
     shift() - Remove e retorna o elemento removido do início.
      push() - Adiciona no final.
       pop() - Remove e retorna o elemento removido do final.
    splice() - Exclui um ou mais elementos.







   # Unidimensional.
   unshift(@uni, "Começo");
   unshift(@uni, "Próximo", "Seguinte");
   push(@uni, "Sexto");
   push(@uni, "Sétimo", "Oitavo");
   my $primeiro = shift(@uni);
   my $ultimo   = pop(@uni);
   splice(@uni, 3, 1); # Onde 3 é o offset e 1 é o tamanho.







   # Bidimensional.
   unshift(@bi, ["Primeiro", "Segundo", "Terceiro", "Quarto", "Quinto"]);
   unshift(@{$bi[0]}, "Começo", "Próximo", "Seguinte");
   push(@bi, ["Primeiro", "Segundo", "Terceiro", "Quarto", "Quinto"]);
   push(@{$bi[0]}, "Sexto", "Sétimo", "Oitavo");
   my $primeiro = shift(@{$bi[0]});
   my $ultimo   = pop(@{$bi[0]});
   splice(@{$bi[0]}, 3, 1);







   # Tridimensional.
   unshift(@tri, [["Primeiro", "Segundo", "Terceiro", "Quarto", "Quinto"]]);
   unshift(@{$tri[0]}, ["Primeiro", "Segundo", "Terceiro", "Quarto"]);
   unshift(@{$tri[0][0]}, "Começo", "Próximo", "Seguinte");
   push(@tri, [["Primeiro", "Segundo", "Terceiro", "Quarto", "Quinto"]]);
   push(@{$tri[0]}, ["Primeiro", "Segundo", "Terceiro", "Quarto"]);
   push(@{$tri[0][0]}, "Sexto", "Sétimo", "Oitavo");
   my $primeiro = shift(@{$tri[0][0]});
   my $ultimo   = pop(@{$tri[0][0]});

1.4. Fatias

Vamos supor que você queira apenas uma seqüência de elementos do array, isso é possível pelo uso do operador "..".

   # Unidimensional.
   my @fatia_uni = @uni[0..3];







   # Bidimensional.
   my @fatias_bi;
   for my $x (0..$#bi) {
    push(@fatias_bi, [ @{$bi[$x]}[0..3] ]);
   }







   # Tridimensional.
   my @fatias_tri;
   for my $x (0..$#tri) {
    for my $y (0..$#{$tri[$x]}) {
     push(@fatias_tri, [ @{$tri[$x][$y]}[0..3] ]);
    }
   }

2. Hashes

Também conhecido como "Listas Associativas". São identificadas pelo símbolo "%". Hash: "Uma associação desordenada de pares chave/valor, armazenada de modo que você possa usar facilmente uma chave de string para procurar seu valor de dados associado". (Programação Perl, Ed. 3, pág. 1017) Bom isto nada mais é do que associar vários nomes a um valor escalar, ou seja, fazer referências a listas de escalares.

2.1. Criando

Em hashes o offset é uma string e não mais um inteiro como no array, tornando esta estrutura um tanto "divertida" de se trabalhar.

   # Unidimensional.
   my %uni_numeros = ("Primeiro", 1, "Segundo", 2, "Terceiro", 3, "Quarto", 4);
   my %uni_sons = (
                   Vaca   => "moooo",
                   Pato   => "quack",
                   Cavalo => "whinny",
                   Ovelha => "bee",
                   Peru   => "cluck",
                   Porco  => "oink"
                   );







   # Bidimensional.
   my %bi_sons = (
                      E => {
                            vaca   => "moooo",
                            pato   => "quack",
                            cavalo => "whinny",
                            ovelha => "bee",
                            peru   => "cluck",
                            porco  => "oink",
                           },
                   Tres => {
                            vaca   => "moooo",
                            pato   => "quack",
                            cavalo => "whinny",
                            ovelha => "bee",
                            peru   => "cluck",
                            porco  => "oink",
                           },
                  Cinco => {
                            vaca   => "moooo",
                            pato   => "quack",
                            cavalo => "whinny",
                            ovelha => "bee",
                            peru   => "cluck",
                            porco  => "oink",
                           },
                 );







   # Tridimensional.
   my %tri_sons = (
                   Entao => {
                             a => { "vaca", "moooo", "ovelha", "bee" },
                             o => { "pato", "quack", "cavalo", "whinny" },
                            },
                  );

2.2. Acessando

Como descrito o offset para acessar os elementos do hash é uma string podendo utilizar aspas (") ou não.

     each - Retorna uma lista de dois elementos contendo chave e valor.
     keys - Retorna uma lista contendo todas as chaves.
     sort - Classifica e retorna a lista.
   values - Retorna uma lista contendo todos os valores.







   # Unidimensional.
   $uni_numeros{Primeiro};
   $uni_sons{vaca};

   for my $indice (keys %uni_sons) { # Elementos desordenados.
    print "$indice faz $uni_sons{$indice}.\n";
   }

   for my $indice (sort keys %uni_sons) { # Elementos ordenados.
    print "$indice faz $uni_sons{$indice}.\n";
   }

   my @indice = keys %uni_sons;    # Pegando o índice.
   my @valores = values %uni_sons; # Pegando os valores.

   while (my ($indice, $valor) = each %uni_sons) { # Índice e valor.
    print "$indice faz $valor.\n";
   }







   # Bidimensional.
   $bi_sons{Tres}{vaca};

   for my $i (keys %bi_sons) { # Elementos desordenados.
    for my $j (keys %{$bi_sons{$i}}) {
     print "$i $j faz $bi_sons{$i}{$j}.\n";
    }
   }

   for my $i (sort keys %bi_sons) { # Elementos ordenados.
    for my $j (sort keys %{$bi_sons{$i}}) {
     print "$i $j faz $bi_sons{$i}{$j}.\n";
    }
   }

   my @indice = keys %bi_sons;       # Pegando o índice.
   my @subindice = keys %{$bi_sons{E}};
   my @valores = values %{$bi_sons{E}}; # Pegando os valores.

   for my $i (keys %bi_sons) { # Índice e valor.
    while (my ($indice, $valor) = each %{$bi_sons{$i}}) {
     print "$i $indice faz $valor.\n";
    }
   }







   # Tridimensional.
   $tri_dons{Entao}{a}{vaca};

   for my $i (keys %tri_sons) { # Elementos desordenados.
    for my $j (keys %{$tri_sons{$i}}) {
     for my $k (keys %{$tri_sons{$i}{$j}}) {
      print "$i $j $k faz $tri_sons{$i}{$j}{$k}.\n"
     }
    }
   }

   for my $i (sort keys %tri_sons) { # Elementos ordenados.
    for my $j (sort keys %{$tri_sons{$i}}) {
     for my $k (sort keys %{$tri_sons{$i}{$j}}) {
      print "$i $j $k faz $tri_sons{$i}{$j}{$k}.\n";
     }
    }
   }

   my @indice = keys %{$tri_sons{Entao}{a}};    # Pegando o índice.
   my @valores = values %{$tri_sons{Entao}{a}}; # Pegando os valores.

   for my $i (keys %tri_sons) { # Índice e valor.
    for my $j (keys %{$tri_sons{$i}}) {
     while (my ($indice, $valor) = each %{$tri_sons{$i}{$j}}) {
      print "$i $j $indice faz $valor.\n";
     }
    }
   }

2.3. Adicionando e Removendo

Veja como é flexível esta estrutura.

   # Unidimensional.
   $uni_sons{Trem} = "piui";  # Adicionando.
   delete($uni_sons{Ovelha}); # Removendo







   # Bidimensional.
   $bi_sons{Um}{trem} = "piui"; # Adicionando.
   $bi_sons{Sete} = {
                     vaca   => "moooo",
                     pato   => "quack",
                     cavalo => "whinny",
                     ovelha => "bee",
                     peru   => "cluck",
                     porco  => "oink",
                    };
   delete($bi_sons{Sete}{porco}); # Removendo
   delete($bi_sons{Sete});







   # Tridimensional.
   $tri_sons{Entao}{o}{trem} = "piui"; # Adicionando.
   delete($tri_sons{Entao}{o}{pato});  # Removendo.

2.4. Fatias

Caso você queira apenas alguns valores do hash isto é possível listando os elementos desejados dentro das {}.

   # Unidimensional.
   my @uni_fatia = @sons{"Vaca", "Porco", "Cavalo", "Trem"};







   # Bidimensional.
   my @bi_fatia = @{$sons{E}}{"vaca", "porco", "cavalo"};







   # Tridimensional.
   my @tri_fatia = @{$sons{Entao}{a}}{"vaca", "ovelha"};

3. Misturando

Agora misturando estas duas estruturas poderemos obter grandes facilidades em relação a flexibilidade.

3.1. Arrays de Hashes

Este é útil quando se tem uma lista de chaves e valores (registros).

   # Criando.
   @array = (
             {
              user => "geek",
              pass => "geekpass",
             },
             {
              user => "freak",
              pass => "freakpass",
             },
            );

   # Acessando.
   $array[0]{user};

   # Adicionando.
   unshift(@array, { user => "lary", pass => "larypass" });
   push(@array, { user => "monger", pass => "mongerpass" });

   # Removendo.
   delete($array[0]);

   # Imprimindo.
   for my $i (0..$#array) {
    for my $j (keys %{$array[$i]}) {
     print "$i - $j == $array[$i]{$j}\n";
    }
   }

3.2. Hashes de Arrays

Podemos usar esta estrutura quando tivermos uma lista atribuída a uma chave.

   # Criando.
   my %hash = {
               lab01 => [ "maria", "joao", "jose" ],
               lab02 => [ "ana", "cleusa", "elza" ],
              };

   # Acessando.
   $hash{lab01}[0];

   # Adicionando.
   unshift(@{$hash{lab01}}, "sonia");
   push(@{$hash{lab01}}, "fernanda");

   # Removendo.
   my $primeiro = shift(@{$hash{lab01}});
   my $ultimo = pop(@{$hash{lab01}});

   # Imprimindo.
   for my $i (keys %hash) {
    for my $j (0..$#{$hash{$i}}) {
     print "user $i: $hash{$i}{$j}\n";
    }
   }

4. Bibliografia

* Online

* Título: PerlDSC man page?
* Descrição: Documentação oficial sobre estrutura de dados em perl.

----

AUTHOR

Fabiano Reese Righetti

blog comments powered by Disqus