Categorias
Introdução à Programação para Bioinformática com Perl

Arrays

Capítulo 4

Este conteúdo faz parte do livro “Introdução à Programação para Bioinformática com Perl“. Você pode adquirir a versão impressa desse livro aqui ou a versão para Kindle aqui. Para nos citar, consulte este link.

Arrays (ou arranjos) são estruturas de dados que armazenam coleções de elementos, ou seja, armazenam uma lista de valores. Arrays podem armazenar variáveis de diversos tipos, como strings, números inteiros e flutuantes. Em Perl, arrays são declarados com o caractere arroba “@”. No exemplo abaixo, vemos a declaração de um array que armazena strings. Os valores devem ser declarados separados por vírgula.

my @nucleotideos = ("A", "T", "C", "G");
print @nucleotideos; # ATCG

Arrays permitem armazenar até mesmo outros arrays, e assim sucessivamente.

my @nomes_nucleotideos= (
"Adenina",
"Timina",
"Citosina",
"Guanina"
);

my @nucleotideos = ("A", "T", "C", "G",@nomes_nucleotideos);

print "@nucleotideos "; 
# A T C G Adenina Timina Citosina Guanina

Para imprimir um array basta chamar o comando print indicando como parâmetro o array. Observe que o comando print imprime os resultados em seguida. Inserindo o array entre aspas, um espa-çamento é inserindo entre os resultados.

Acessando elementos individualmente dentro de um array

É possível acessar cada elemento de um array como se fosse uma variável através dos chamados índices. Para isso o índice deve ser indicado entre colchetes. O índice representa a posição em cada elemento foi declarado. Lembre-se que a contagem sempre come-ça pelo valor 0, ou seja, para retornar o terceiro elemento de uma lista é necessário chamar a posição [2] do array.

my @nucleotideos = ("A", "T", "C", "G");
print $nucleotideos[2]; # C

Note que para acessar individualmente cada elemento é utilizado o símbolo “$” ao invés de “@”.

Arrays podem ainda ser iniciados sem qualquer valor e preenchidos durante a execução do script.

my @array_vazio = ();

Inserindo e removendo elementos em um array

Dado um array já declarado, podemos inserir novos elementos utilizando o comando push. A função push adiciona os novos elementos ao final do array.

my @aminoacidos = ("Alanina","Cisteina","Aspartato");

# Inserindo um novo elemento
push(@aminoacidos, "Glutamato");

# Inserindo mais de um elemento por vez
push(@aminoacidos, "Fenilalanina","Glicina","Histidina");

print "@aminoacidos ";
# Alanina Cisteina Aspartato Glutamato 
# Fenilalanina Glicina Histidina

Para remover o último elemento de uma lista podemos utilizar a função pop. A função pop não apenas remove o elemento da lista, mas também o retorna.

my @aminoacidos = ("Alanina","Cisteina","Aspartato");
my $ultimo_elemento = pop(@aminoacidos);

print "Elemento removido: $ultimo_elemento\n";
# Aspartato

print "Nova lista: @aminoacidos\n";
# Alanina Cisteina

Contando o número de elementos em um array

Podemos contar a quantidade de elementos de um array atribuindo-o a uma variável escalar. Veja:

my @aminoacidos = ("Alanina","Cisteina","Aspartato");

# Retorna o tamanho do array
my $numero_de_elementos = @aminoacidos; 
print $numero_de_elementos; # 3

Convertendo arrays em variáveis escalares

Atribuindo um array a uma variável escalar obtemos o seu tamanho, entretanto se o array for declarado entre aspas, todos os seus elementos serão separados em ordem por um espaçamento e convertidos em string. Veja:

my @aminoacidos = ("Alanina","Cisteina","Aspartato");

# Retorna o tamanho do array
my $numero_de_elementos = @aminoacidos;

# Converte array em uma variavel escalar
my $conteudo_array = "@aminoacidos";
print "O array \@aminoacidos possui $numero_de_elementos elementos. Sao eles: $conteudo_array.\n";

# O array @aminoacidos possui 3 elementos. 
# Sao eles: Alanina Cisteina Aspartato.

Observe que foi utilizada uma barra invertida antes da variável @aminoacidos. A barra invertida antes do símbolo de arroba indica ao Perl que o caractere a seguir não deve ser processado e sim impresso como um simples caractere. Assim o texto “@aminoacidos” é impresso ao invés do conteúdo do array.

Outras operações para manipulação de arrays

É possível ainda realizar outras operações para manipular arrays, como por exemplo remover os primeiros elementos e extrair partes do array.

my @aminoacidos = ("Alanina","Cisteina","Aspartato");

# Recebe os dois primeiros elementos de @aminoacidos
(my $um, my $dois) = @aminoacidos;
print $um."\n"; # Alanina
print $dois."\n"; # Cisteina

# Atribui duas variaveis de uma vez
(my $um_copia,my $dois_copia) = ($um, $dois);
print $um_copia."\n"; # Alanina
print $dois_copia."\n"; # Cisteina

# Armazena o primeiro elemento em uma variavel 
# e o resto em outro array
(my $primeiro,my @outros_elementos) = @aminoacidos;
print $primeiro."\n"; # Alanina
print "@outros_elementos\n"; # Cisteina Aspartato

# Extrai parte dos aminoácidos (de 0 ate 1)
my @alguns_aminoacidos = @aminoacidos[0..1];
print "@alguns_aminoacidos\n"; # Alanina Cisteina

Hashes

Conhecidas também como arrays associativos ou dicionários, hashes podem ser definidas como estruturas de dados que apresentam chave e valor. Diferente dos arrays que permitem a associação de variáveis escalares com posições numéricas, hashes permitem a vinculação de uma string única a um valor.

Em Perl, hashes devem ser declaradas precedidas do caractere “%”. Os elementos de uma hash devem ser declarados separados por vírgula e devem possuir a seguinte estrutura: “chave” => “valor”.

# Vinculando um aminoacido a uma letra
my %aminoacidos = ("A" => "Alanina", "C" => "Cisteina");

print $aminoacidos{"A"}; # Alanina

Observe que para acessar o valor de um elemento presente em uma determinada hash é necessário chamá-la como se fosse uma variável escalar (ou seja, precedida do símbolo “$”) e adicionar entre chaves “{}” o nome da chave identificadora.

No exemplo acima imprimimos o valor relativo a chave “A”, ou seja, “Alanina”. Lembre-se que dentro de uma hash devemos ter chaves únicas, ou seja, no nosso exemplo podemos ter diversos valores chamados “Alanina”, mas apenas uma chave chamada “A”.

Inserindo e removendo elementos em uma hash

Para inserir novos elementos a uma hash é necessário declarar uma nova variável escalar, com o mesmo nome da hash e com uma chave que seja única.

Para remover elementos de uma hash utilize a palavra reservada delete seguida do nome da hash (iniciado com $) e o valor da chave que deseja apagar. No exemplo a seguir, vamos inserir uma nova chave “D”, cujo valor será “Aspartato”, e remover a chave “C”, cujo valor é “Cisteina”.

my %aminoacidos = ("A" => "Alanina", "C" => "Cisteina");

$aminoacidos{"D"} = "Aspartato";
print %aminoacidos; #DAspartatoCCisteinaAAlanina
print "\n";
delete $aminoacidos{"C"};
print %aminoacidos; #DAspartatoAAlanina

Observe que a chave “D” e o valor “Aspartato” foram inseridos na hash, entretanto a impressão está desconfigurada. Nos próximos capítulos aprenderemos mais sobre como iterar sobre hashes e arrays.

Obtendo-se o tamanho de uma hash

Para obter-se o tamanho de uma hash podemos contar a quantidade de chaves utilizando a palavra reservada keys. A palavra reservada keys permite o acesso às chaves da hash.

Nesse caso, o comando “$tamanho = keys %aminoacidos;” gravaria na variável $tamanho a quantidade de chaves presentes na hash %aminoacidos. Uma outra forma de fazer isso seria utilizando a palavra reservada scalar. Lembre-se que Perl permite que tarefas sejam feitas de diversas maneiras.

my %aminoacidos = ("A" => "Alanina", "C" => "Cisteina");
print scalar keys %aminoacidos;

Inserindo arrays como valores em uma hash

Hashes permitem que quaisquer tipos de variáveis sejam inseridos como valores, inclusive arrays. Para acessá-los é necessário imprimir a hash como uma variável escalar informando a posição da chave e a posição do vetor.

my %aminoacidos = (
	polares => ["Aspartato","Glutamato"],
	apolares => ["Alanina","Cisteina"]	
);

print $aminoacidos{polares}[0]; # Aspartato
print $aminoacidos{apolares}[1]; # Cisteina

Nesse exemplo imprimimos o primeiro elemento do array armazenado na chave “polares”. Note que não é obrigatório declarar a chave entre aspas.

Extraindo listas de chaves e valores

É possível extrair chaves e valores armazenados em uma hash e gravá-las em arrays. Para isso utilizamos a palavra-chave keys (chaves) e a palavra-chave values (valores).

my %aminoacidos = (
polares, ["Aspartato","Glutamato"], 
apolares,["Alanina","Cisteina"]
);

my @tipos = keys %aminoacidos;
my @aminoacidos = values %aminoacidos;

print "\nTipos: @tipos";
print "\nAminoacidos: @aminoacidos";

Observe como a hash %aminoacidos foi declarada: cada chave seguida por seu determinado valor.

Observe também que ao imprimir o array @aminoacidos, que armazena os valores de %aminoacidos, obtemos como resultado: “ARRAY(0x7fa3f18060e8)” e “ARRAY(0x7fa3f182eac8)”. Isso é exibido porque o array @aminoacidos armazena um outro array. Para visualizar esses resultados é necessário utilizar o módulo Dumper, ou então, iterar sobre os resultados, o que aprenderemos mais a frente.

Ordenando arrays

Para ordenar arrays, Perl fornece a função sort. A função sort permite a ordenação por código ASCII de elementos presentes em um array.

my @aminoacidos = (
"Cistenia","Serina","Valina",
"Alanina","Fenilalanina","Glutamato"
);
my @aminoacidos_ordenados = sort @aminoacidos;

print "@aminoacidos_ordenados\n";
# Alanina Cistenia Fenilalanina Glutamato Serina Valina

O código ASCII de uma mesma letra maiúscula e minúscula é diferente, o que na prática indica que a ordenação padrão da função sort é case senstive, ou seja, diferencia maiúsculas e minúsculas.

Observe que a ordenação por código ASCII é similar a uma ordenação alfabética. Entretanto, o que aconteceria se tentássemos ordenar valores numéricos?

Ordenando arrays numéricos

Números também estão representados na tabela ASCII. Entretanto, a função sort compara cada casa decimal individualmente. Isso quer dizer na prática que valores numéricos terão uma ordenação mais próxima à alfabética do que à numérica. Por exemplo, o valor “1” é menor do que “2”, logo se ordenados ficariam nas posições corretas. Entretanto, se nessa lista ainda existisse o valor “10”, ele seria inserido entre “1” e “2”, pois na ordenação por código ASCII o primeiro caractere é comparado primeiro, em seguida o segundo com o segundo, e assim sucessivamente. Logo, o primeiro caractere de “10” é “1”, que é menor do que “2”. Então pela ordenação por código ASCII, “10” vem antes de “2”. Veja o exemplo a seguir:

# ORDENACAO POR CÓDIGO ASCII
my @numeros = (19, 1, 13, 27, 2, 4);
my @numeros_ordenados = sort @numeros;

print "Numeros nao ordenados:  
 @numeros\nNumeros ordenados com sort: 
 @numeros_ordenados\n";

# Numeros nao ordenados:        19 1 13 27 2 4
# Numeros ordenados com sort:   1 13 19 2 27 4

Observe que o array numérico @numeros_ordenados não está corretamente ordenado 1, 13, 19, 2, 27 e 4. Para solucionar esse problema podemos utilizar o operador de comparação numérica “<=>”.

# ORDENACAO NUMERICA
my @numeros = (19, 1, 13, 27, 2, 4);
my @numeros_ordenados = sort { $a <=> $b } @numeros;

print "Numeros nao ordenados:    
@numeros\nNumeros ordenados com sort:   
@numeros_ordenados\n";

# Numeros nao ordenados:        19 1 13 27 2 4
# Numeros ordenados com sort:   1 2 4 13 19 27

Dica: criando arrays numéricos rapidamente

Para criar um array numérico composto por uma grande quantidade de elementos rapidamente pode-se utilizar a seguinte sintaxe:

my @numbers = (1..500);
print "@numbers\n";

No exemplo anterior, criamos um array com 500 valores que vão de 1 a 500.

Ordenando hashes

No exemplo a seguir faremos a ordenação de uma hash, entretanto vamos criá-la de uma maneira diferente. Criaremos um array chamado @produtos. Em seguida, usando a função push iremos inserir duas chaves (nome e valor), e faremos inserção de três produtos (A, B e C) com distintos preços. Por fim, faremos a ordenação da hash com base na chave valor e iremos imprimir os resultados ordenados pelo valor.

my @produtos;
my @ordenados;

push @produtos, { nome => "A", valor => 7.80 };
push @produtos, { nome => "B", valor => 3.99 };
push @produtos, { nome => "C", valor => 5.58};

@ordenados =  reverse sort { $a->{valor} <=> $b->{valor} } @produtos;

print join "\n", map {$_->{nome}." - ".$_->{valor}} @ordenados;
print "\n";

Observe que os valores foram ordenados corretamente do menor para o maior. Se quiséssemos ordenar decrescentemente, ou seja, do maior para o menor poderíamos utilizar a palavra reservada reverse antes do comando sort.

@ordenados =  reverse sort { $a->{valor} <=> $b->{valor} } @produtos;

Na impressão dos resultados apresentamos uma nova função: join. O comando join recebe uma lista de strings e as une através de um separador, que no exemplo foi o caractere especial “\n”. Apresentamos também a função map. Essa função permite uma análise individual de cada elemento da lista. Observe a variável “$_”. Perl define que quando um nome de variável não for especificado para receber cada elemento, a variável “$_” armazenará temporariamente os valores em questão.

Módulo Data::Dumper

Algumas vezes você se irá se deparar com hashes a qual não sabe exatamente seu conteúdo. O módulo Data::Dumper permite a conversão de estruturas de dados em Perl para strings.

my %aminoacidos = (polares => ["Aspartato","Glutamato"],  apolares => ["Alanina","Cisteina"]);

print %aminoacidos;
# apolaresARRAY(0x8dad84)polaresARRAY(0x8dac54)

use Data::Dumper;
print Dumper %aminoacidos;
# $VAR1 = 'apolares';
# $VAR2 = [
#          'Alanina',
#          'Cisteina'
#        ];
# $VAR3 = 'polares';
# $VAR4 = [
#          'Aspartato',
#          'Glutamato'
#        ];

Observe que nossa hash chamada %aminoacidos armazena as chaves polares e apolares, e cada uma dessas chaves tem como valores um array. Se tentarmos imprimi-los com um simples comando print, Perl retorna que naquela posição existe um array (ARRAY(0x8dad84)).

Utilizando o comando Dumper em conjunto com o comando print, Perl imprimirá na tela todo o conteúdo da hash em forma de string.

A função Dumper permite visualizar todo o conteúdo de uma hash ou de um array sem conhecê-lo por completo. Entretanto, Perl fornece meios de “navegar” pelo conteúdo de arrays, analisando individualmente cada elemento. No próximo capítulo veremos outros comandos do Perl capazes de percorrer arrays: laços de repetição.

Quer aprender mais? Conheça nossos cursos profissionalizantes à partir de R$19,99:

Nota do autor
Prefácio

Capítulo 1
Introdução ao Perl

Capítulo 2
Comandos condicionais

Capítulo 3
Strings

Capítulo 4
Arrays

Capítulo 5
Laços de repetição

Capítulo 6
Manipulando arquivos

Capítulo 7
Sub-rotinas

Capítulo 8
“O guia de sobrevivência para expressões regulares em Perl”

Capítulo 9
Introdução ao BioPerl

Capítulo 10
Sequências

Capítulo 11
BLAST

Capítulo 12
Estruturas de proteínas

Capítulo 13
Hierarquia do BioPerl

Epílogo
Referências bibliográficas
Sobre os autores

Por favor, nos cite:

MARIANO, DIEGO CÉSAR BATISTA; de MELO-MINARDI, R. C. . Introdução à Programação para Bioinformática com Perl. 1. ed. North Charleston, SC (EUA): CreateSpace Independent Publishing Platform, 2016. v. 2. 200p .

Por Diego Mariano

Doutor em Bioinformática pela Universidade Federal de Minas Gerais com atuação na área de ciência de dados e aprendizado de máquina aplicados ao aperfeiçoamento de enzimas usadas na produção de biocombustíveis. Mestre em Bioinformática, também pela UFMG, atuando na área de desenvolvimento de sistemas Web para montagem de genomas. Atualmente realiza estágio pós-doutoral no Departamento de Ciência da Computação da UFMG com foco em desenvolvimento de sistemas Web para Bioinformática, análise exploratória e visualização de dados. Tem conhecimentos nas linguagens: PHP, JavaScript, Python, R, Perl, HTML, CSS e SQL.