Estrutura de dados

Manipulando mapas no Dart

Os mapas são coleções de dados organizados em um formato chave-valor. Cada elemento inserido em um mapa no Dart possui uma chave a ele relacionado. Os mapas são estruturas muito úteis quando precisamos relacionar cada elemento com um identificador único. Sendo assim, veremos neste artigo os principais métodos para manipulação de mapas no Dart.

Declarando mapas

A declaração de mapas no Dart pode ser feita de duas formas. A primeira é utilizando o construtor da classe Map() , como podemos ver abaixo:

void main() { 
   var usuario = new Map(); 
   usuario['usuario'] = 'admin'; 
   usuario['senha'] = 'admin123'; 
   print(usuario); 
}

O código acima irá criar um mapa e o armazenará na variável usuarioe adicionará as chaves usuario e senha, além de armazenar seus respectivos dados.

A segunda forma de declarar mapas no Dart é utilizando o formato “literal”, adicionando os dados iniciais do mapa entre chaves {}:

void main() { 
   var usuario = {'usuario':'admin','senha':'admin123'}; 
   print(usuario); 
}
Dart - Fundamentos
Curso de Dart - Fundamentos
CONHEÇA O CURSO

Retornando elementos pelo índice

Como vimos anteriormente, a principal característica dos mapas é o armazenamento no formato chave-valor, onde cada valor estará relacionado a uma chave. Com essa estrutura, há casos em que precisamos obter o valor de uma determinada chave.

Para isso, no Dart, é bem simples. Basta acessarmos a chave do elemento que queremos retornar entre colchetes [], como podemos ver abaixo:

void main() { 
   var usuario = new Map(); 
   usuario['usuario'] = 'admin'; 
   usuario['senha'] = 'admin123'; 
   print(usuario['usuario']); 
}

O código acima irá retornar o valor relacionado à chave usuario.

Adicionando elementos

Há duas formas para adicionarmos novos elementos a um dicionário. A primeira é atrelando um elemento a uma chave, como fizemos nos exemplos anteriores:

void main() { 
   var usuario = new Map(); 
   usuario['usuario'] = 'admin'; 
   usuario['senha'] = 'admin123'; 
   usuario['cargo'] = 'gerente';
   print(usuario); 
}

Adicionando elementos no mapa

Já a segunda forma é utilizando o método addAll(), passando como parâmetro uma estrutura no formato chave-valor como parâmetro:

void main() { 
   var usuario = new Map(); 
   usuario['usuario'] = 'admin'; 
   usuario['senha'] = 'admin123'; 
   usuario['cargo'] = 'gerente';
   var novosDados = {'nome': 'Joao', 'sobrenome': 'Silva'};
   usuario.addAll(novosDados);
   print(usuario); 
}

Adicionando elementos com addAll

Removendo elementos de um mapa

Para remover elementos de um mapa, utilizamos o método remove() e passamos a chave do elemento a ser removido:

void main() { 
   var usuario = new Map(); 
   usuario['usuario'] = 'admin'; 
   usuario['senha'] = 'admin123'; 
   usuario['cargo'] = 'gerente';
   var novosDados = {'nome': 'Joao', 'sobrenome': 'Silva'};
   usuario.addAll(novosDados);
   print(usuario); 
   usuario.remove('usuario');
  print(usuario);
}

Removendo elementos nos mapas

Limpando mapas

Há casos em que precisamos limpar toda a estrutura de um mapa. Para isso, o Dart provê o método clear(), como podemos ver abaixo:

void main() { 
   var usuario = new Map(); 
   usuario['usuario'] = 'admin'; 
   usuario['senha'] = 'admin123'; 
   usuario['cargo'] = 'gerente';
   var novosDados = {'nome': 'Joao', 'sobrenome': 'Silva'};
   usuario.addAll(novosDados);
   print(usuario); 
   usuario.clear();
   print(usuario);
}

Limpando mapas

Manipulando listas no Dart

Uma lista é a estrutura de dados mais básica do Dart. Sua estrutura permite armazenar dados em sequência, onde cada elemento possui sua posição de origem, sendo o primeiro elemento armazenado no índice zero e, a cada elemento novo, o índice é incrementado. Com o Dart, há diversos métodos para manipulação de listas, como veremos neste artigo.

Declarando Listas no Dart

As listas no Dart podem ser declaradas de duas formas. A primeira é especificando o seu tamanho total, como podemos ver abaixo:

void main() { 
   var lista = new List(3); 
   lista[0] = 1; 
   lista[1] = 2; 
   lista[2] = 3; 
   print(lista); 
}

O código acima irá criar uma lista com 3 posições disponíveis para armazenar novos elementos.

Já a segunda forma é quando não especificamos o tamanho total da lista e, assim, podemos armazenar quantos elementos forem necessários:

void main() { 
   var lista = new List(); 
   lista.add(1); 
   lista.add(2); 
   print(lista); 
}
Flutter - Fundamentos
Curso de Flutter - Fundamentos
CONHEÇA O CURSO

Imprimindo listas

A impressão de listas no Dart é bem simples, basta utilizarmos o método print() e adicionarmos o nome da lista como parâmetro:

void main() {
   var lista = new List(); 
   lista.add(1); 
   lista.add(2); 
   var lista2 = new List(3); 
   lista2[0] = 1; 
   lista2[1] = 2; 
   lista2[2] = 3; 
   print(lista); 
   print(lista2); 
}

O código acima irá retornar o seguinte resultado:

Imprimindo Listas

Inserindo elementos na lista

A inserção de elementos em uma lista pode ser feito de duas formas, utilizando o método add() ou atribuindo um valor a uma determinada posição, como podemos ver abaixo:

void main() {
   var lista = new List(); 
   lista.add(1); 
   var lista2 = new List(3); 
   lista2[0] = 1; 
   print(lista); 
   print(lista2); 
}

Retornando tamanho da lista

Para retornar o tamanho de uma lista no Dart, podemos utilizar a propriedade length:

void main() {
   var lista = new List(); 
   lista.add(1); 
   lista.add(2);
   lista.add(3);
   lista.add(4);
     print("O tamanho da lista é: ${lista.length}");
}

O código acima irá imprimir o tamanho total da lista:

Retornando tamanho da lista

Removendo elementos da lista

Existem diversas formas de remover elementos de uma lista no Dart, a primeira é utilizando o método remove() , passando o valor a ser removido como parâmetro:

void main() {
   var lista = new List(); 
   lista.add(1); 
   lista.add(2);
   lista.add(3);
   lista.add(4);
   lista.remove(2);
   print(lista);
}

Removendo elementos da lista

A segunda forma de remover elementos de uma lista no Dart é utilizando o método removeAt() e passando a posição do elemento a ser removido:

void main() {
   var lista = new List(); 
   lista.add(1); 
   lista.add(2);
   lista.add(3);
   lista.add(4);
   lista.removeAt(2);
   print(lista);
}

Removendo posição da lista

A terceira forma é utilizando o método removeLast() , que removerá o último elemento da lista:

void main() {
   var lista = new List(); 
   lista.add(1); 
   lista.add(2);
   lista.add(3);
   lista.add(4);
   lista.removeLast();
   print(lista);
}

Removendo ultimo elemento

A última forma é utilizando o método removeRange() , que vai remover os elementos de um intervalo específico:

void main() {
   var lista = new List(); 
   lista.add(1); 
   lista.add(2);
   lista.add(3);
   lista.add(4);
   lista.removeRange(0, 2);
   print(lista);
}

Removendo elementos em um intervalo

Manipulando dicionários no Python

Como vimos no artigo sobre as principais estruturas de dados no Python, os dicionários são coleções de itens desordenados com uma diferença bem grande quando comparados às outras coleções (lists, sets, tuples, etc): um elemento dentro de um dicionário possui uma chave atrelada a ele, uma espécie de identificador.

Sendo assim, é muito utilizado quando queremos armazenar dados de forma organizada e que possuem identificação única (como acontece em bancos de dados).

Neste artigo, veremos como manipular os dicionários com os principais métodos disponibilizados pela API de Collections do Python.

meu_dicionario = {1 : 'Fabio', 2 : 'Maria', 3 : 'João', 4 : 'José'}
print(type(meu_dicionario))

meu_dicionario_2 = dict({1 : 'Fabio', 2 : 'Maria', 3 : 'João', 4 : 'José'})
print(type(meu_dicionario_2))
Python - Fundamentos
Curso de Python - Fundamentos
CONHEÇA O CURSO

O código acima, que pode ser visto no seguinte link (https://onlinegdb.com/BJhaeI1fL), criará dois dicionários, o primeiro utilizando as chaves ({}) e separando os elementos das suas chaves com dois pontos (:) e o segundo utilizando o método dict(). As duas formas terão o mesmo resultado:

Retornando elementos pelo índice

Para retornar um elemento pelo seu índice de um dicionário, há duas formas. A primeira é passando, entre colchetes ([]) o índice do elemento desejado. Já a segunda é utilizando o método get() com a posição do elemento como parâmetro:

meu_dicionario = {1 : 'Fabio', 2 : 'Maria', 3 : 'João', 4 : 'José'}

#get()
print(meu_dicionario[2])
print(meu_dicionario.get(4))

A execução do código acima terá o seguinte resultado (https://onlinegdb.com/rJxkr81GI):

Retornando o tamanho de um dicionário

Para retornar o tamanho de um dicionário, podemos utilizar o método len() e passar o dicionário a ser analisado como parâmetro:

meu_dicionario = {1 : 'Fabio', 2 : 'Maria', 3 : 'João', 4 : 'José'}

#len()
print(len(meu_dicionario))

A execução do código acima terá o seguinte resultado (https://onlinegdb.com/HyIcSU1fL):

Adicionando elementos em um dicionário

Para inserir novos elementos em um dicionário, existem duas formas. A primeira é passar o valor ao índice de um dicionário e a segunda é utilizando o método update(), passando como parâmetro a chave e o elemento a ser adicionado:

meu_dicionario = {1 : 'Fabio', 2 : 'Maria', 3 : 'João', 4 : 'José'}

meu_dicionario[5] = 'Joaquina'
print(meu_dicionario)

meu_dicionario.update({6: 'Pedro'})
print(meu_dicionario)

A execução do código acima terá o seguinte resultado (https://onlinegdb.com/rkzPLI1zI):

Removendo elementos de um dicionário

Para remover elementos de um dicionário utilizamos o método pop() seguido do índice do elemento que deve ser removido. Isso fará com que o elemento seja removido, como podemos ver no código abaixo:

meu_dicionario = {1 : 'Fabio', 2 : 'Maria', 3 : 'João', 4 : 'José'}

#pop()
meu_dicionario.pop(2)
print(meu_dicionario)

A execução do código acima terá o seguinte resultado (https://onlinegdb.com/H1u2ILkfL):

Conclusão

Os dicionários provêem uma ótima forma para armazenar dados organizados e com um padrão simples de entender, como vimos neste artigo. Saber manipulá-los é fundamental para utilizá-los em nossos projetos.

Manipulando sets no Python

Os sets são uma coleção de itens desordenada, parcialmente imutável e que não podem conter elementos duplicados. Por ser parcialmente imutável, os sets possuem permissão de adição e remoção de elementos.

Além disso, os sets são utilizados, normalmente, com operações matemáticas de união, interseção e diferença simétrica, conforme veremos nos próximos tópicos.

Neste artigo, veremos como manipular os sets com os principais métodos disponibilizados pela API de Collections do Python.

Declarando Sets

Para declarar um set no Python é bem simples. Seus elementos devem estar entre chaves ({}) ou utilizando o método set() do próprio Python, como podemos ver abaixo:

 # Declaração de um set
meu_set = {1, 2, 3, 4, 1}
print(type(meu_set))

meu_set_2 = set([1, 2, 8, 9, 10])
print(type(meu_set_2))

O código acima, que pode ser visto no seguinte link (https://onlinegdb.com/rkPa6QyZ8), criará dois sets, o primeiro utilizando as chaves ({}) e separando os elementos por vírgula (,) e o segundo utilizando o método set(). As duas formas terão o mesmo resultado:

Adicionando, atualizando e removendo elementos dos Sets

Os sets permitem as operações de adição, atualização e remoção de elementos. Para isso, existe um método para cada funcionalidade, como podemos ver abaixo:

meu_set = {1, 2, 3, 4, 1}

# Adicionando elementos
meu_set.add(2)
print("Adição", meu_set)

# Atualizando set
meu_set.update([3, 4, 5, 6])
print("Atualição", meu_set)

# Removendo elemento
meu_set.discard(2)
print("Remoção", meu_set)

Como podemos ver no trecho de código acima, o método add() é responsável por adicionar um elemento ao set, desde que ele já não esteja adicionado, pois os sets não permitem elementos duplicados.

Python - Fundamentos
Curso de Python - Fundamentos
CONHEÇA O CURSO

Já o método update() permite atualizar os sets e adicionar os elementos (que não estejam duplicados) em sua estrutura.

Por fim, o método discard() permite a remoção de um elemento do set.

Operações matemáticas com Sets

Os sets, além das operações de manipulação vistas anteriormente, permitem operações matemáticas como união, interseção, diferença e diferença simétrica, conforme veremos abaixo.

meu_set = {1, 2, 3, 4, 1}
meu_set_2 = set([1, 2, 8, 9, 10])

# União
print("União")
print(meu_set | meu_set_2)
print(meu_set.union(meu_set_2))

# Interseção
print("Interseção")
print(meu_set & meu_set_2)
print(meu_set.intersection(meu_set_2))

# Diferença
print("Diferença")
print(meu_set - meu_set_2)
print(meu_set.difference(meu_set_2))

# Diferença Simétrica
print("Diferença Simétrica")
print(meu_set ^ meu_set_2)
print(meu_set.symmetric_difference(meu_set_2))

O resultado da execução acima pode ser vista no seguinte link: https://onlinegdb.com/Sk_hsEJ-U.


Na união ( | ), todos os elementos dos dois sets serão “unidos” em um, formando um único set com todos os elementos, sem repetí-los, claro.

Na Interseção ( & ), apenas os elementos que estiverem nos dois sets restarão.

Já na diferença ( – ), restarão apenas os elementos que estiverem em um dos set, mas não no segundo.

Por fim, na diferença simétrica ( ^ ), apenas os elementos que estiverem nos dois sets, porém que não se repitam, serão exibidos.

Manipulando tuplas no Python

Como vimos no artigo “Principais estruturas de dados no Python”, as tuplas são estruturas bastante similares às listas, com apenas uma diferença: os elementos inseridos em uma tupla não podem ser alterados, diferente de uma lista onde podem ser alterados livremente. Sendo assim, em um primeiro momento, podemos pensar em uma tupla como uma lista que não pode ser alterada, mas não é bem assim…

É certo que as tuplas possuem diversas características das listas, porém os usos são distintos. As listas são destinadas a serem sequências homogêneas, enquanto que as Tuplas são estruturas de dados heterogêneas.

Sendo assim, apesar de bastante similares, a tupla é utilizada para armazenar dados de tipos diferentes, enquanto que a lista é para dados do mesmo tipo. No Python, há diversos métodos para manipulação de tuplas, como veremos no decorrer deste artigo.

Python - Collections
Curso de Python - Collections
CONHEÇA O CURSO

Declarando Tuplas

A sintaxe para criação de uma tupla, assim como uma lista, também é bem simples. Ao invés de se utilizar colchetes (listas), são utilizados parênteses, como podemos ver abaixo:

nome_da_tupla1 = (1, 2, 3) #tupla de inteiros
nome_da_tupla2 = (1, "olá", 1.5) #tupla heterogênea

O resultado da execução do código acima pode ser visto no seguinte link: https://onlinegdb.com/r1Jr4CdyI

Contando elementos em uma Tupla

Para verificar a quantidade de elementos existentes em uma tupla, podemos utilizar o método count() e enviando o valor que queremos verificar como parâmetro:

nome_da_tupla1 = (1, 2, 3) #tupla de inteiros

print(nome_da_tupla1.count(1))
nome_da_tupla1 = (1, 1, 2, 3)
print(nome_da_tupla1.count(1))

O resultado da execução acima pode ser visto na imagem abaixo e no seguinte link: https://onlinegdb.com/r13yIDi18

Exibir o índice de um determinado elemento

Para retornar o índice de um determinado elemento em uma tupla, utilizamos o método index(), enviando o valor que queremos pesquisar como parâmetro:

nome_da_tupla1 = (1, 2, 3) #tupla de inteiros

print(nome_da_tupla1.index(3))

O resultado da execução acima pode ser visto na imagem abaixo e no seguinte link: https://onlinegdb.com/Hk1WPvikL

Verificar a existência de um elemento na Tupla

Um outro recurso muito utilizado em tuplas é a verificação da existência de um determinado elemento. Para isso, utilizamos o in do Python, como podemos ver abaixo:

nome_da_tupla1 = (1, 2, 3) #tupla de inteiros

print(2 in nome_da_tupla1)
print(22 in nome_da_tupla1)

O código acima retornará um True caso o elemento seja encontrado e um False caso não (https://onlinegdb.com/B1iB_wiJU):

Considerações finais

Assim como as listas, as tuplas são ótimas formas para armazenamento de elementos, principalmente se você não quer permitir que estes elementos sejam alterados. Neste artigo vimos algumas das principais funcionalidades das tuplas e suas aplicações.

No próximo artigo desta série veremos como manipular outras estruturas de dados com o Python. Até lá 🙂

Manipulando listas no Python

Vimos no último artigo as principais estruturas de dados presentes no Python, dentre elas, as listas, estrutura mais básica do Python.

Basicamente, uma lista é a estrutura de dados mais básica do Python e armazena os dados em sequência, onde cada elemento possui sua posição na lista, denominada de índice. O primeiro elemento é sempre o índice zero e a cada elemento inserido na lista esse valor é incrementado.

No Python, há diversos métodos para manipulação de listas, conforme veremos neste artigo.

Declarando Listas

A declaração de listas no Python é bem simples. Basicamente, devemos informar, entre colchetes ([]) o conteúdo da lista separados em vírgulas (,):

lista_simples_inteiro = [1, 2, 3, 8, 14, 4, 5]
listas_simples_string = ["Olá", "Mundo"]
lista_simples_mesclada = [1, 2, 3, "Olá, mundo", True, 1.5]

Nos exemplos acima, estamos declarando três listas com diferentes tipos de dados. Vale lembrar que uma lista pode conter diferentes tipos de dados, porém não é recomendado a utilização de uma lista para armazenar dados de diferentes tipos em uma mesma estrutura. Nestes casos, a Tupla é a estrutura de dados mais recomendada.

Imprimindo Listas

A impressão de listas no Python é muito simples. Basicamente, utilizamos o método print() e enviamos o nome da lista de queremos imprimir como parâmetro:

lista_simples_inteiro = [1, 2, 3, 8, 14, 4, 5]
listas_simples_string = ["Olá", "Mundo"]
lista_simples_mesclada = [1, 2, 3, "Olá, mundo", True, 1.5]

print(lista_simples_inteiro)
print(listas_simples_string)
print(lista_simples_mesclada)

O resultado da execução do código acima pode ser visto no seguinte link: https://onlinegdb.com/HkKIutU6B:

Inserindo elementos na lista

A inserção de elementos em uma lista pode ser feito por dois métodos, o append() e o insert(). O método append() insere o elemento sempre no final da lista, já o insert() irá inserir o elemento em uma posição específica:

lista_simples_inteiro = [1, 2, 3, 8, 14, 4, 5]

print(lista_simples_inteiro)

# Append()
lista_simples_inteiro.append(6)
print(lista_simples_inteiro)

# Insert()
lista_simples_inteiro.insert(2, 100)
print(lista_simples_inteiro)
Python - Estrutura de dados - Parte 1
Curso de Python - Estrutura de dados - Parte 1
CONHEÇA O CURSO

Com a execução do código acima, teremos o seguinte resultado (https://onlinegdb.com/B1Fr7qUTH):

Pode-se notar que o método append() inseriu o valor 6 no final da lista, já o método insert() inseriu o elemento 100 na posição 2 da lista.

Retornando tamanho da Lista

Para retornar o tamanho de uma lista no Python, podemos utilizar o método len() e passar a lista como parâmetro (https://onlinegdb.com/Bklftc86H):

lista_simples_inteiro = [1, 2, 3, 8, 14, 4, 5]

print(lista_simples_inteiro)

# Len()
print(len(lista_simples_inteiro))

Removendo elementos na lista

Para remover elementos de uma lista, utilizamos o método remove(), passando o elemento que queremos excluir da lista como parâmetro (https://onlinegdb.com/ryWR55U6r):

lista_simples_inteiro = [1, 2, 3, 8, 14, 4, 5]

print(lista_simples_inteiro)

# Remove()
lista_simples_inteiro.remove(5)
print(lista_simples_inteiro)

Dividindo listas

No Python, há duas formas de “cortar” listas. A primeira é utilizando os colchetes ([]) para determinar o intervalo do “corte” e a segunda é utilizando o método slice(), passando o intervalo como parâmetro:

lista_simples_inteiro = [1, 2, 3, 8, 14, 4, 5]

print(lista_simples_inteiro)

print(lista_simples_inteiro[0:4]) # Cortar lista da posição 0 a 4 (sem incluir a 4)
print(lista_simples_inteiro[1:]) # Cortar lista da posição 1 em diante
print(lista_simples_inteiro[:3]) # Cortar lista do início até a posição 3 (sem incluir a 3)
nova_lista = lista_simples_inteiro[:3] # Criar uma nova lista com base no corte de outra lista
print(nova_lista)

intervalo = slice(1, 4) # Cortar a lista a partir da posição 1 até a 4 (sem incluir a 4)
print(lista_simples_inteiro[intervalo])

Conclusão

As listas são uma ótima forma para armazenar elementos, como vimos neste artigo. Saber manipulá-las é fundamental para que possamos desenvolver nossos projetos e utilizar os melhores recursos da linguagem.

Porém, no Python, as listas não são as únicas estruturas de dados existentes. No próximo artigo desta série veremos como manipular uma outra estrutura bastante utilizada, os Sets.

Principais Estruturas de Dados no Python

No Python, podemos utilizar diversos tipos de estruturas de dados. Estas estruturas resolvem um tipo de problema e podem ser úteis em diversas situações. As principais estruturas são as Listas, Sets, Dicionários e Tuplas e neste artigo veremos as diferenças e principais características de cada uma.

Listas

Uma lista é a estrutura de dados mais básica do Python e armazena os dados em sequência, onde cada elemento possui sua posição na lista, denominada de índice. O primeiro elemento é sempre o índice zero e a cada elemento inserido na lista esse valor é incrementado.

No Python, uma lista pode armazenar qualquer tipo de dado primitivo (string, inteiro, float, etc). Na imagem abaixo podemos ver como uma lista se comporta:

Declarando Listas

Para a criação de uma lista no Python, a sintaxe é a seguinte:

nome_da_lista = [] # Criação de uma lista vazia
nome_da_lista = [1, 2, 3] # Criação de uma lista de inteiros
nome_da_lista = [1, "Olá, mundo!", 1.1] # Criação de uma lista com vários tipos diferentes

Podemos também criar listas dentro de outras listas. Essas são chamadas de nested lists e sua sintaxe é a seguinte:

nome_da_lista = ["Olá, mundo",  [1, 2, 3], ["outra_lista"]]

Possuímos aqui no blog um artigo que mostra os principais métodos de manipulação de listas no Python.

Tuplas

Uma tupla é uma estrutura bastante similar a uma lista, com apenas uma diferença: os elementos inseridos em uma tupla não podem ser alterados, diferente de uma lista onde podem ser alterados livremente. Sendo assim, em um primeiro momento, podemos pensar em uma tupla como uma lista que não pode ser alterada, mas não é bem assim…

É certo que as tuplas possuem diversas características das listas, porém os usos são distintos. As listas são destinadas a serem sequências homogêneas, enquanto que as Tuplas são estruturas de dados heterogêneas.

Sendo assim, apesar de bastante similares, a tupla é utilizada para armazenar dados de tipos diferentes, enquanto que a lista é para dados do mesmo tipo.

Tuplas x Listas

As tuplas possuem algumas vantagens com relação às listas, que são:

  • Como as tuplas são imutáveis, a iteração sobre elas é mais rápida e, consequentemente, possuem um ganho de desempenho com relação às listas;
  • Tuplas podem ser utilizadas como chave para um dicionário, já que seus elementos são imutáveis. Já com a lista, isso não é possível;
  • Se for necessário armazenar dados que não serão alterados, utilize uma tupla. Isso garantirá que esses sejam protegidos de alterações posteriores.

Declarando Tuplas

A sintaxe para criação de uma tupla, assim como uma lista, também é bem simples. Ao invés de se utilizar colchetes (listas), são utilizados parênteses, como podemos ver abaixo:

nome_da_tupla = (1, 2, 3) #tupla de inteiros
nome_da_tupla = (1, "olá", 1.5) #tupla heterogênea

Possuímos aqui no blog um artigo que mostra os principais métodos de manipulação de tuplas no Python.

Sets

No Python, os sets são uma coleção de itens desordenada, parcialmente imutável e que não podem conter elementos duplicados. Por ser parcialmente imutável, os sets possuem permissão de adição e remoção de elementos.

Além disso, os sets são utilizados, normalmente, com operações matemáticas de união, interseção e diferença simétrica, conforme veremos nos próximos tópicos.

Desenvolvedor Python Júnior
Formação: Desenvolvedor Python Júnior
Aprenda os principais conceitos do Python (uso de variáveis, estruturas condicionais e estruturas de decisão), como trabalhar com orientação à objetos (métodos, construtores, destrutores, classes, herança, polimorfismo e duck-typing) e estruturas de dados (Listas, Filas, Pilhas, Árvores Binárias, Dicionários, Conjuntos, Tabelas de Espalhamento e Mapas).
CONHEÇA A FORMAÇÃO

Declarando Sets

Para a criação de um set no Python há duas formas: A primeira é bem similar às listas e tuplas, porém utilizando chaves {} para determinar os elementos do set:

nome_do_set = {1, 2, 3, 4}

A segunda é utilizando o método set presente no Python:

nome_do_set = set([1, 2, 3, 4])

Possuímos aqui no blog um artigo que mostra os principais métodos de manipulação de sets no Python.

Dicionários

No Python, os dicionários são coleções de itens desordenados com uma diferença bem grande quando comparados às outras coleções (lists, sets, tuples, etc): um elemento dentro de um dicionário possui uma chave atrelada a ele, uma espécie de identificador. Sendo assim, é muito utilizado quando queremos armazenar dados de forma organizada e que possuem identificação única (como acontece em bancos de dados).

Um dicionário, portanto, pode ser visto como a figura abaixo:


Onde cada valor é “atrelado” à uma chave, seu identificador. Vale lembrar que, por necessitar que cada valor possua uma chave relacionada a ele, as chaves dos dicionários devem ser únicas para que possam ser acessadas, também, através do seu índice.

As chaves também não são armazenadas em qualquer ordem, elas apenas são associadas aos valores que pertencem.

Declarando Dicionários

Existem duas formas de se criar um dicionário utilizando o Python. A primeira delas é utilizando chaves ( {} ) e separando os elementos das chaves com dois pontos ( : ) e os outros elementos por vírgula ( , ):

nome_do_dicionario = {1: ‘João’, 2: ‘José’}
nome_do_dicionario = {‘nome’: ‘João’, ‘sobrenome’: ‘Silva’}

A segunda forma é utilizando o método dict() com o dicionário sendo passado como parâmetro:

nome_do_dicionario = dict({1: ‘João’, 2: ‘José’})
nome_do_dicionario = dict({‘nome’: ‘João’, ‘sobrenome’: ‘Silva’})

Possuímos aqui no blog um artigo que mostra os principais métodos de manipulação de sets no Python.

Animou?

No Python, possuímos diversas estruturas prontas para utilizar, como vimos neste artigo, e cada uma resolve um tipo de problema. No próximo artigo, iniciaremos os estudos mais aprofundados de cada uma destas estruturas e como manipulá-las no Python.

Até lá 🙂

Você conhece o GraphQL e como ele pode te ajudar?

Olá, Web Developers!

Muitos aqui já devem ter ouvido falar desse tal GraphQL há algum tempo, mas sem saber ainda o que ele é e por que deveríamos cogitá-lo na nossa stack de desenvolvimento. Talvez ele seja uma boa pedida para o seu projeto.

Vamos entendê-lo um pouco mais?

React - Despertando o Poder dos Hooks
Curso de React - Despertando o Poder dos Hooks
CONHEÇA O CURSO

Como tudo começou

O GraphQL começou no Facebook. Imagine que para exibir uma lista de posts era necessário o acesso a uma API, e dentro de cada post tinha que vir uma lista dos usuários que curtiram. Dentro de cada objeto de usuário tem que vir o nome, foto do perfil, link para o perfil, se o usuário já é seu amigo, etc.

Pelo menos é isso que nós podemos ver quando acessamos o Facebook pelo navegador. Mas quando estamos no aplicativo mobile, não temos todas essas informações do usuário. O que temos é uma lista de usuários que curtiram e o link para seu perfil.

Poderíamos então evitar que o servidor nos envie dados que não vamos precisar, deixando o nosso app mobile mais rápido e economizando dados (bom para quem está no 3G ou 4G).

Mas, sério, não é legal criar uma nova API apenas para enviar uma estrutura levemente diferente, como “mobile/posts”.

É muito comum também que, em sistemas maiores, os dados fiquem em diferentes bases de dados. Podemos, por exemplo, ter dados relacionais no MySQL, guardar certas informações em forma de documentos no MongoDB e ter pequenos dados para consultas rápidas no Redis.

É aqui que começamos a ver que teremos um bom trabalho: juntar dados de bancos diferentes e enviar uma estrutura diferente para cada tipo de aplicação.

O GraphQL entra em cena

GraphQL

Ao invés de ter que ficar criando uma API para cada estrutura diferente de dados e/ou ficar manualmente fazendo consultas para cada banco e depois juntar os dados, que tal simplesmente dizer a “alguém” o que você precisa?

Para fazermos uma consulta no GraphQL, teríamos algo parecido com isso:

query {
   posts
}

Declaramos uma consulta com query e indicamos que queremos um campo com o nome posts.

Também podemos criar consultas que tenham mais níveis, como:

query {
   posts {
      likes
      comments
      shares
   }
}

É possível, ainda, passar parâmetros, como:

query {
   posts (userId: 157321){
      likes
      comments
      shares
   }
}

Dúvidas comuns

Não gosto de ferramentas do Facebook

O GraphQL é mais uma especificação. Então você pode usar outras ferramentas que fazem o mesmo e que não sejam do Facebook.

Uma ferramenta parecida, que visa resolver o mesmo problema, é o Falcor, desenvolvida pela Netflix.

Se eu for trabalhar com GraphQL, terei que usar React?

Não. O GraphQL pode ser usado com qualquer framework, biblioteca ou linguagem de programação.

A ideia do cliente dizer o que quer não me parece segura…

Fique tranquilo. O GraphQL tem uma coisa chamada resolvers. Com eles você pode cuidar da segurança de seus dados, permitindo ou não que determinado usuário acesse-os.

Ainda acho que não preciso disso. Minha aplicação já está muito boa com as APIs existentes.

Se você acredita que não tem problema e que a sua solução hoje já funciona perfeitamente, ótimo.

A ideia do GraphQL é ajudar a solucionar determinado problema. Se você não tem esse problema em sua aplicação, realmente você não precisa gastar tempo implementando uma ferramenta a mais.

Concluindo

O GraphQL é uma linguagem de consulta que facilita o nosso trabalho na hora de fazer requisições, basta que indiquemos os campos que queremos sem que nos preocupemos de onde os dados estão vindo.

Caso queira fazer alguns testes, acesse o GitHub GraphQL.

Tente executar, por exemplo, a seguinte query:

query {
  repository(owner: "graphql", name: "graphql-js"){
    name
    description
  }
}

O que achou do GraphQL? Já teve algum problema que poderia ter sido resolvido com ele? Acha que precisará dele em um novo projeto? Compartilhe com a gente aí nos comentários!

Prototipação Rápida
Curso de Prototipação Rápida
CONHEÇA O CURSO

Conheça os principais algoritmos de ordenação

Imagine como seria buscar um número em um catálogo telefônico se os nomes das pessoas não estivessem listados em ordem alfabética? Seria muito complicado. A ordenação ou classificação de registros consiste em organizá-los em ordem crescente ou decrescente e assim facilitar a recuperação desses dados. A ordenação tem como objetivo facilitar as buscas e pesquisas de ocorrências de determinado elemento em um conjunto ordenado.

Como preza a estratégia algorítmica: “Primeiro coloque os números em ordem. Depois decidimos o que fazer.”

Na computação existe uma série de algoritmos que utilizam diferentes técnicas de ordenação para organizar um conjunto de dados, eles são conhecidos como Métodos de Ordenação ou Algoritmos de Ordenação. Vamos conhecer um pouco mais sobre eles.

Os métodos de ordenação se classificam em:

  • Ordenação Interna: onde todos os elementos a serem ordenados cabem na memória principal e qualquer registro pode ser imediatamente acessado.

  • Ordenação Externa: onde os elementos a serem ordenados não cabem na memória principal e os registros são acessados sequencialmente ou em grandes blocos.

Hoje veremos apenas os métodos de ordenação interna.

Dentro da ordenação interna temos os Métodos Simples e os Métodos Eficientes:

C Básico
Curso de C Básico
CONHEÇA O CURSO

Métodos Simples

Os métodos simples são adequados para pequenos vetores, são programas pequenos e fáceis de entender. Possuem complexidade C(n) = O(n²), ou seja, requerem O(n²) comparações. Exemplos: Insertion Sort, Selection Sort, Bubble Sort, Comb Sort.

Dica: Veja uma breve introdução à análise de algoritmos

Nos algoritmos de ordenação as medidas de complexidade relevantes são:

  • Número de comparações C(n) entre chaves.
  • Número de movimentações M(n) dos registros dos vetores.

Onde n é o número de registros.

Insertion Sort

Insertion Sort ou ordenação por inserção é o método que percorre um vetor de elementos da esquerda para a direita e à medida que avança vai ordenando os elementos à esquerda. Possui complexidade C(n) = O(n) no melhor caso e C(n) = O(n²) no caso médio e pior caso. É considerado um método de ordenação estável.

Um método de ordenação é estável se a ordem relativa dos itens iguais não se altera durante a ordenação.

O funcionamento do algoritmo é bem simples: consiste em cada passo a partir do segundo elemento selecionar o próximo item da sequência e colocá-lo no local apropriado de acordo com o critério de ordenação.


(Imagens: Wikipedia.org)

Vejamos a implementação:

void insercao (int vet, int tam){
int i, j, x;
for (i=2; i<=tam; i++){
    x = vet[i];
    j=i-1;
    vet[0] = x; 
    while (x < vet[j]){
        vet[j+1] = vet[j];
        j--;
    }
    vet[j+1] = x;
}

Para compreender melhor o funcionamento do algoritmo veja este vídeo:

Selection Sort

A ordenação por seleção ou selection sort consiste em selecionar o menor item e colocar na primeira posição, selecionar o segundo menor item e colocar na segunda posição, segue estes passos até que reste um único elemento. Para todos os casos (melhor, médio e pior caso) possui complexidade C(n) = O(n²) e não é um algoritmo estável.


(Imagens: Wikipedia.org)

Veja este vídeo para conhecer o passo a passo de execução do algoritmo:

void selecao (int vet, int tam){
    int i, j, min, x;
    for (i=1; i<=n-1; i++){
        min = i;
    for (j=i+1; j<=n; j++){
            if (vet[j] < vet[min])
            min = j;
    }
    x = vet[min];
    vet[min] = vet[i];
    vet[i] = x;
    }
}

Métodos Eficientes

Os métodos eficientes são mais complexos nos detalhes, requerem um número menor de comparações. São projetados para trabalhar com uma quantidade maior de dados e possuem complexidade C(n) = O(n log n). Exemplos: Quick sort, Merge sort, Shell sort, Heap sort, Radix sort, Gnome sort, Count sort, Bucket sort, Cocktail sort, Timsort.

Quick Sort

O Algoritmo Quicksort, criado por C. A. R. Hoare em 1960, é o método de ordenação interna mais rápido que se conhece para uma ampla variedade de situações.

Provavelmente é o mais utilizado. Possui complexidade C(n) = O(n²) no pior caso e C(n) = O(n log n) no melhor e médio caso e não é um algoritmo estável.

É um algoritmo de comparação que emprega a estratégia de “divisão e conquista”. A ideia básica é dividir o problema de ordenar um conjunto com n itens em dois problemas menores. Os problemas menores são ordenados independentemente e os resultados são combinados para produzir a solução final.

Basicamente a operação do algoritmo pode ser resumida na seguinte estratégia: divide sua lista de entrada em duas sub-listas a partir de um pivô, para em seguida realizar o mesmo procedimento nas duas listas menores até uma lista unitária.

Funcionamento do algoritmo:

  • Escolhe um elemento da lista chamado pivô.
  • Reorganiza a lista de forma que os elementos menores que o pivô fiquem de um lado, e os maiores fiquem de outro. Esta operação é chamada de “particionamento”.
  • Recursivamente ordena a sub-lista abaixo e acima do pivô.

Dica: Conheça um pouco sobre algoritmos recursivos

(Imagem: Wikipedia.org)

Veja este vídeo para conhecer o passo a passo de execução do algoritmo:

void quick(int vet[], int esq, int dir){
    int pivo = esq, i,ch,j;         
    for(i=esq+1;i<=dir;i++){        
        j = i;                      
        if(vet[j] < vet[pivo]){     
            ch = vet[j];               
            while(j > pivo){           
                vet[j] = vet[j-1];      
                j--;                    
            }
            vet[j] = ch;               
            pivo++;                    
        }
    }
    if(pivo-1 >= esq){              
        quick(vet,esq,pivo-1);      
    }
    if(pivo+1 <= dir){              
        quick(vet,pivo+1,dir);      
    }
 }

A principal desvantagem deste método é que ele possui uma implementação difícil e delicada, um pequeno engano pode gerar efeitos inesperados para determinadas entradas de dados.

Mergesort

Criado em 1945 pelo matemático americano John Von Neumann o Mergesort é um exemplo de algoritmo de ordenação que faz uso da estratégia “dividir para conquistar” para resolver problemas. É um método estável e possui complexidade C(n) = O(n log n) para todos os casos.

Esse algoritmo divide o problema em pedaços menores, resolve cada pedaço e depois junta (merge) os resultados. O vetor será dividido em duas partes iguais, que serão cada uma divididas em duas partes, e assim até ficar um ou dois elementos cuja ordenação é trivial.

Para juntar as partes ordenadas os dois elementos de cada parte são separados e o menor deles é selecionado e retirado de sua parte. Em seguida os menores entre os restantes são comparados e assim se prossegue até juntar as partes.


(Imagens: Wikipedia.org)

Veja o vídeo para conhecer o passo a passo da execução do algoritmo:

void mergeSort(int *vetor, int posicaoInicio, int posicaoFim) {
    int i, j, k, metadeTamanho, *vetorTemp;
    if(posicaoInicio == posicaoFim) return;
    metadeTamanho = (posicaoInicio + posicaoFim ) / 2;

    mergeSort(vetor, posicaoInicio, metadeTamanho);
    mergeSort(vetor, metadeTamanho + 1, posicaoFim);

    i = posicaoInicio;
    j = metadeTamanho + 1;
    k = 0;
    vetorTemp = (int *) malloc(sizeof(int) * (posicaoFim - posicaoInicio + 1));

    while(i < metadeTamanho + 1 || j  < posicaoFim + 1) {
        if (i == metadeTamanho + 1 ) { 
            vetorTemp[k] = vetor[j];
            j++;
            k++;
        }
        else {
            if (j == posicaoFim + 1) {
                vetorTemp[k] = vetor[i];
                i++;
                k++;
            }
            else {
                if (vetor[i] < vetor[j]) {
                    vetorTemp[k] = vetor[i];
                    i++;
                    k++;
                }
                else {
                    vetorTemp[k] = vetor[j];
                    j++;
                    k++;
                }
            }
        }

    }
    for(i = posicaoInicio; i <= posicaoFim; i++) {
        vetor[i] = vetorTemp[i - posicaoInicio];
    }
    free(vetorTemp);
}

Shell Sort

Criado por Donald Shell em 1959, o método Shell Sort é uma extensão do algoritmo de ordenação por inserção. Ele permite a troca de registros distantes um do outro, diferente do algoritmo de ordenação por inserção que possui a troca de itens adjacentes para determinar o ponto de inserção. A complexidade do algoritmo é desconhecida, ninguém ainda foi capaz de encontrar uma fórmula fechada para sua função de complexidade e o método não é estável.

Os itens separados de h posições (itens distantes) são ordenados: o elemento na posição x é comparado e trocado (caso satisfaça a condição de ordenação) com o elemento na posição x-h. Este processo repete até h=1, quando esta condição é satisfeita o algoritmo é equivalente ao método de inserção.

A escolha do salto h pode ser qualquer sequência terminando com h=1. Um exemplo é a sequencia abaixo:

h(s) = 1, para s = 1
h(s) = 3h(s - 1) + 1, para s > 1

A sequência corresponde a 1, 4, 13, 40, 121, …

Knuth (1973) mostrou experimentalmente que esta sequencia é difícil de ser batida por mais de 20% em eficiência.

Veja o vídeo que demonstra o passo a passo da execução do algoritmo:

void shellSort(int *vet, int size) {
    int i , j , value;
    int gap = 1;
    while(gap < size) {
        gap = 3*gap+1;
    }
    while ( gap > 1) {
        gap /= 3;
        for(i = gap; i < size; i++) {
            value = vet[i];
            j = i - gap;
            while (j >= 0 && value < vet[j]) {
                vet [j + gap] = vet[j];
                j -= gap;
            }
            vet [j + gap] = value;
        }
    }
}

Conclusão

Neste artigo foi apresentado os principais métodos de ordenação com foco no conceito e funcionamento de cada um deles.

Você pode ver na tabela abaixo a comparação entre eles:

(Imagem: DECOM – UFOP)

Um abraço e até a próxima!

Python - SQLAlchemy ORM
Curso de Python - SQLAlchemy ORM
CONHEÇA O CURSO

Desmistificando os algoritmos recursivos

Os algoritmos recursivos são fundamentais na solução de muitos problemas envolvendo a computação, ainda assim, muitos programadores os veem como algo complexo e de difícil implementação.

Como disse o prof. Siang Wun Song:

Para fazer um procedimento recursivo é preciso ter fé.

Calma! Apesar da fala do prof. Siang, implementar um algoritmo recursivo não é um bicho de sete cabeças. Veremos alguns passos para compreendê-los de vez. o/

C Básico
Curso de C Básico
CONHEÇA O CURSO

Primeiro devemos entender o que é a recursividade. Uma função recursiva chama a si mesma dentro do próprio escopo. Pode ser uma recursão direta onde uma função A chama a própria função A ou uma recursão indireta onde uma função A chama uma função B que por sua vez chama a função A. Além de chamar a si mesma, a função recursiva deve possuir uma condição de parada que a impedirá de entrar em loop infinito.

Antes de criar uma função recursiva para determinado problema, é preciso saber se ele possui uma estrutura recursiva. Neste caso, devemos verificar se parte do problema possui o mesmo tipo do original, assim podemos dizer que a solução para ele é a recursividade. Para compreender melhor, vamos analisar o caso do somatório onde temos um número natural n >= 0 e queremos descobrir a soma de todos os números de n até 0.

Antes de criar o algoritmo devemos extrair dois elementos do problema: O caso base que se tornará a condição de parada e o passo recursivo. Vejamos algumas possíveis iterações do problema:

No caso do somatório, é possível identificar que para cada valor de n o último elemento sempre é 0, assim podemos confirmar que este é o caso base.

Analisando um pouco mais as iterações temos que para cada valor de n vamos diminuindo em 1 até que chegue ao valor 0.

Assim, nós temos que o somatório de um número natural n é o próprio n adicionado ao somatório do número antecessor (Somatório de n = n + (n-1) + (n-2) + ... + 0). Logo, o nosso passo recursivo é n + soma(n-1).

Sabemos que o caso base é 0 e o somatório de 0 é ele mesmo, estão essa será a nossa condição de parada. O nosso passo recurso é n + soma(n-1), assim já temos os elementos da nossa função recursiva e podemos criá-la:

int soma(int n){
    if(n == 0)
        return 0;
    return n + soma(n-1);
}

Esta é a implementação em C para resolver o problema de forma recursiva. Para um número natural n informado, a função irá executar até que seja encontrado o caso base e assim retornar o valor do somatório.

Vamos analisar outro problema clássico que pode ser resolvido com recursividade: o fatorial de um número natural n >= 1. O fatorial é bem semelhante ao somatório, porém é feito com multiplicação sucessiva.

Vamos analisar as possíveis iterações:

No exemplo do fatorial, o nosso caso base é 1, portanto, a nossa condição de parada será verificar se o número é 1 e, caso seja, a função deverá retorná-lo. Também é possível definir o nosso passo recursivo: fatorial de n = n x (n - 1) x (n - 2) x ... x 1 logo n! = n x fatorial(n - 1). Por fim, chegamos à seguinte implementação em C:

int fatorial(int n){
    if(n == 1)
        return 1;
    return n * fatorial(n-1);
}

Uma grande vantagem da recursividade é o fato de gerar uma redução no tamanho do algoritmo, permitindo descrevê-lo de forma mais clara e concisa. Porém, todo cuidado é pouco ao se fazer módulos recursivos. Basta seguir estes passos e você não terá grandes problemas. Como disse L. Peter Deutsch:

Iterar é humano, fazer recursão é divino.

Um abraço e até a próxima!

C Avançado
Curso de C Avançado
CONHEÇA O CURSO

© 2004 - 2019 TreinaWeb Tecnologia LTDA - CNPJ: 06.156.637/0001-58 Av. Paulista, 1765, Conj 71 e 72 - Bela Vista - São Paulo - SP - 01311-200