Fabiano Reese RighettiPublicado em 19/08/2006
r2 - 19 Aug 2006 - JoenioCosta
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.
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];
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"],
],
);
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";
}
}
}
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]});
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] ]);
}
}
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.
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" },
},
);
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";
}
}
}
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.
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"};
Agora misturando estas duas estruturas poderemos obter grandes facilidades em relação a flexibilidade.
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";
}
}
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";
}
}
----
Fabiano Reese Righetti