Alura > Cursos de Programação > Cursos de Python > Conteúdos de Python > Primeiras aulas do curso Python Collections parte 2: conjuntos e dicionários

Python Collections parte 2: conjuntos e dicionários

Conjuntos - Introdução

Meu nome é Guilherme Silveira e nesse curso de Introdução às Coleções: Parte 2, vamos ver outras coleções do Python que acabamos utilizando bastante no dia a dia. Então nesse curso vamos ver os sets, os dicionários e suas variações, como um defaultdict ou um counter.

Vamos também utilizar tudo isso com o que a já vimos no curso que é pré-requisito, onde vemos listas e tuplas, então vamos acabar utilizando listas, tuplas, conjuntos, dicionários, defaultdict e counter, tudo isso misturado com list comprehension, etc. Dentro desse curso.

Então ele vai dar a base dessas outras coleções que existem no Python e são super úteis no dia a dia. Para esse curso, vamos utilizar o Google Colab, você pode utilizar o Júpyter Notebook na sua máquina ou o Python, Python 3, o interpretador na linha de comando ou ainda o PyCharm, o que você quiser, sinta-se à vontade.

Vamos lá?

Conjuntos - Trabalhando com conjuntos, os sets

Começando o nosso curso, eu vou usar o Google Colab, como estávamos fazendo no curso anterior de coleções, então eu vou criar um novo notebook do Python usando a versão 3.

O nome vai ser "Continuando com Collections", e a ideia é continuarmos trabalhando com outros tipos de coleções de elementos. Lembrando quando eu estou falando de uma coleção de elementos, quer dizer que eu estou representando diversos elementos de uma maneira única, um conjunto de elementos, e eu tenho diversas maneiras de agrupar elementos - uma delas a tradicional lista do Python: os colchetes.

Então eu tenho, por exemplo, uma lista no meu sistema que representa os usuários que se cadastraram em um curso da Alura, ou compraram um produto, ou que leram um livro, o que você quiser. No meu caso, são os usuários que se cadastraram no curso de Data Science, tudo bem? Os usuários se cadastram no curso de Data Science.

Tenho quatro usuários, para dar exemplo, eu tenho o 15, o 23, o 43 e 56. Quatro usuários que se cadastraram neste curso. Eu tenho também os usuários que se cadastraram no curso de Introdução à Machine Learning, então são áreas próximas, de alguma maneira. Machine learning.

usuarios_data_science = [15, 23, 43, 56]
usuarios_machine_learning = [13, 23, 56, 42]

No curso de Introdução à Machine Learning também tenho quatro usuários. Por coincidência, o usuário 13, o usuário 23, o usuário 56, o usuário 42. Então repara que quatro usuários fizeram o curso de Data Science, quatro usuários fizeram o curso de Machine Learning – introdução. Só dando um exemplo aqui.

E o que eu quero trabalhar aqui? Eu queria pensar o seguinte: Dei o “Shift + Enter” para rodar e eu quero pegar agora as pessoas que fizeram os cursos dessa área, de Data Science ou Machine Learning, e enviar um e-mail para elas, notificando de um curso novo que saiu. Por exemplo, saiu um curso novo agora, que é uma continuação de Machine Learning e Data Science, e aí eu queria notificar essas pessoas.

Então o que eu quero pegar é o identificador, o número, de todas essas pessoas. Então como é que eu faço para juntar todas essas pessoas que assistiram todos esses cursos, todas essas pessoas que estão aí? Então as pessoas que assistiram os dois cursos, os usuários de Data Science e de Machine Learning.

Vou começar com uma lista vazia e agora o que eu queria fazer é: pegar todo mundo que está aqui em usuarios_data_science e colocar aqui dentro de assistiram. No curso básico de coleções, vemos várias funções, vários métodos de objetos do tipo lista. Dentro desses métodos, tinha um método que era o método extend(). O extend() recebe uma coleção, um iterador, usuários Data Science, e vai passar por cada elemento desses iteração, desse iterável, e colocar aqui dentro.

Então, teremos no final o assistiram, vamos ver o assistiram? Tem que ficar entre colchetes igual aos usuarios_data_science e está. Mas repara que se na prática o que eu estou fazendo é exatamente uma cópia, eu posso literalmente copiar a minha lista, e uma lista, se você procurar documentação do Python como "Python documentation" no Google, que eu sempre reforço a importância de não termos medo de procurar a documentação e aprender a explorar. Você vai ver que se você procurar aqui copy(), adivinha? Existe um método que devolve uma cópia dessa lista.

Um ponto importante: ele fala shallow copy, uma cópia rasa, superficial. O que quer dizer uma cópia superficial ou rasa? Quer dizer que se você tem objetos aqui dentro, por exemplo, quatro contas: uma conta corrente ou uma conta poupança, ele não vai tirar uma cópia dessas contas, ele vai colocar referências para as mesmas contas.

Para o nosso caso, que estamos trabalhando com tipos inteiros, não importa, queremos simplesmente uma cópia desse meu usuários_data_science. Então usuários_data_science.copy() tira uma cópia e cada um dos elementos está com o mesmo valor, que é o 15, 23, 43, 56. Vamos testar? É uma cópia. No nosso caso, só vamos usar essa cópia simples mesmo.

assistiram = usuarios_data_science.copy()
assistiram

[15, 23, 43, 56]

O que eu queria agora é estender com esses elementos. Então agora sim, assistiram.extend(usuários_machine_learning). Vamos testar?

assistiram = usuarios_data_science.copy()
assistiram.extend(usuarios_machine_learning)
assistiram

[15, 23, 43, 56, 13, 23, 56, 42]

E agora eu tenho quantas pessoas mesmo? len(assistiram) eu tenho 8 pessoas para as quais eu vou enviar o e-mail. E aí eu envio o e-mail e o que acontece? Eu recebo duas reclamações. Por que eu recebo duas reclamações? Dá uma olhada para quem que eu enviei e-mail.

len(assistiram)

8

Enviei um e-mail para pessoa 15, enviei um e-mail para pessoa 23, enviei um e-mail para a pessoa 43, um e-mail para pessoa 56. Envie um e-mail para pessoa 13, enviei para o 23? Já estava aqui o 23. Enviei dois e-mails para pessoa 23, enviei dois e-mails para 56. Então o que aconteceu foi: esses meus dois conjuntos aqui que são listas, são duas listas que possuem elementos repetidos entre si, existe uma intersecção aqui entre esses dois conjuntos que não é vazia, que é o elemento 23 e o elemento 56.

Em situações comuns do dia a dia, uma lista é o que queremos, então pode ter elemento repetido, pode não ter elemento repetido, tanto faz. Eu quero o acesso àquela lista de elementos. Mas tem situações em que eu não quero manter elementos repetidos. Se alguém tentar colocar um elemento repetido lá dentro, ignora. Então quando eu tenho uma lista de elementos e não quero pegar os elementos de forma repetida, isso é: quero pegar no máximo uma vez cada elemento, temos uma definição que costuma ser usado nessa área de coleções, que é o que chamamos realmente de conjunto em inglês, e aí sim conjunto em inglês, uma palavra técnica é o set(), "S-E-T".

Esse tipo de conjunto vem daquele conjunto da Matemática: conjunto dos números reais, conjuntos dos números naturais, etc. Um conjunto, então posso pegar o assistiram, que é uma lista, e transformar em um conjunto. O que é que acontece? Quando transformamos uma lista em conjunto, reparamos que ele mudou um pouco a representação, e aqui a gente tem o 13, o 15, o 23, o 42, o 43, o 56. Só seis elementos. Não tem mais elementos repetidos.

set(assistiram)

{13, 15, 23, 42, 43, 56}

Então um conjunto no Python é representado aqui por vários elementos, que não possuem elementos repetidos. Não conseguimos replicar elementos lá dentro, colocar duas vezes o mesmo elemento. Claro, provavelmente aqui atrás também era capaz de já termos usado conjuntos, poderíamos já ter usado logo de cara conjuntos.

Então para eu criar um conjunto, eu venho aqui e digito conjunto e passo uma lista, por exemplo: elemento 1, 2, 3 e rodo. Então passando uma lista para um conjunto, ele nos devolve um conjunto. Se eu passar aqui o mesmo elemento duas vezes? Ele vai ignorar a segunda aparição. Então eu posso passar de novo um iterável que vai ser transformado em um conjunto.

set([1,2,3,1])

{1, 2, 3}

Mas como um conjunto é razoavelmente comum, podemos direto usar essa anotação de conjunto, eu poderia ter usado aqui direto. Pula para a próxima linha, 1, 2, 3, 1, e eu tenho o meu conjunto. Só para mostrar, se eu colocar o elemento 4 aqui, 1, 2, 3, 1, eu tenho esses meus elementos, por coincidência apareceu aqui em ordem do menor para o maior, mas não precisa necessariamente aparecer nessa ordem, pode aparecer em qualquer ordem.

{4, 1,2,3,1}

{1, 2, 3, 4}

Então a notação para criar um conjunto simples é a chaves. Você pode sempre testar o tipo de um objeto usando o type(), dá uma conferida no tipo. Vou criar aqui um conjunto, imprimo, o tipo é conjunto, set. Então set é legal por quê? Porque dado um iterável você consegue excluir as repetições, deixando somente uma vez de cada elemento. É uma maneira de fazer isso.

Só que é claro, se eu já sabia que eu só poderia aparecer uma vez aqui cada um dos usuários e a ordem não precisa ser necessariamente a ordem de entrada, então 15 é o primeiro elemento, 23 o segundo, 43, 56, repara que eu comecei com 4, 1, 2, 3, 1 e a saída foi 1, 2, 3, 4, não foi a ordem de entrada, não foi 4, 1, 2, 3. Então se o acesso sequencial não precisa ser alguma coisa importante, aquela podia ser importante: esse é o primeiro usuário que se cadastrou, segundo usuário, então eu usaria uma lista.

Mas se isso não importa, se essa ordem não importa, a ordem das posições não importam, eu posso usar aqui um conjunto, que já logo de cara eu já garanto que cada um desses só vai aparecer uma vez. Então a ordem, nesse meu caso, estou considerando a ordem não importa. Vamos mostrar aqui? A ordem não necessariamente foi a ordem de entrada. O conjunto já me dá isso logo de cara, então vai depender do que você precisa: a ordem não importa? Usa assim direto um conjunto.

usuarios_data_science = {15, 23, 43, 56}
usuarios_machine_learning = {13, 23, 56, 42}
usuarios_machine_learning

{13, 23, 42, 56}

Agora, será que o conjunto tem um acesso aleatório, isso é a posição três? Quem é a posição três? A posição 3 de entrada? É o 13, 23, 56, 42? Ou é a posição três que ele está imprimindo na representação aqui de string para nós? 0, 1, 2, 3 a 56? Então quando você tenta acessar aleatoriamente um conjunto, você não possui indexação. Um acesso aleatório à uma posição, porque o que eu falei: não existe posição, tudo bem?

Diferente da lista, onde a posição é importante, o primeiro é o primeiro, o segundo é o segundo, terceiro é o terceiro, quarto é o quarto elemento, é isso aí. No conjunto não, o conjunto é um conjunto, é uma bola, é uma esfera, é um espaço, com um monte de coisa dentro. Não tem primeiro, segundo, terceiro, quarto e quinto. Tem os elementos lá dentro, pronto.

Então, o conjunto tem uma vantagem, do elemento aparecer de forma única, lá dentro, porém tem outras "desvantagens" ou características que indicam que você não quer utilizar um set, que é se você quiser usar um elemento específico, pegar o terceiro, eu quero uma ordem lá dentro, por padrão, um conjunto não possui ordem, mas você pode iterar como qualquer iterável, então for usuario in qual que é o nosso conjunto que tem todo mundo? O Assistiram, o set de assistiram seria com todo mundo.

Então se eu passar pelo set de assistiram, eu imprimo um usuário aqui e deveria imprimir seis usuários, olha, os seis usuários. Repara que a ordem, é uma ordem x, uma ordem qualquer que apareceu, que não nos importa, que lembra que eu falei? Conjunto, por padrão, não virá em uma ordem que necessariamente gostaríamos ou não gostaríamos. Eles virão, essa é a ideia do conjunto.

for usuario in set(assistiram):
  print(usuario)

42

43

13

15

23

56

Então resolve esse problema para nós e conseguimos acessar, iterar, imprimir, fazer o que quiser com esse conjunto dessa maneira. "Mas Gui, se eu tenho dois conjuntos já, em vez de duas listas, como é que eu faço então para pegarmos a união desses dois conjuntos?" Então eu tenho esses dois conjuntos, então eu quero os elementos que estão no primeiro ou no segundo, tanto faz, ou no primeiro ou no segundo.

Então vou copiar isso daqui, então usuarios_data_science e usuarios_machine_learning eu quero quem está no Data Science ou, o símbolo de ou, esse é o símbolo de ou, é o “Shift + \” na maior parte dos teclados, chamamos de pipe |. usuarios_data_science | usuarios_machine_learning. Então eu quero os elementos que estão ou aqui ou aqui, tanto faz. Pode até ser que esteja nos dois. E fazemos isso e aqui temos os seis elementos. Tudo bem?

usuarios_data_science = {15, 23, 43, 56}
usuarios_machine_learning = {13, 23, 56, 42}
usuarios_data_science | usuarios_machine_learning

{13, 15, 23, 42, 43, 56}

Então, entre aspas, o "equivalente" ao extend(), seria a operação de “ou”. Por quê? Porque ou está aqui, ou está aqui, ou está nos dois, tanto faz. Essa é a operação de “ou” e aí temos o que? A união dos dois conjuntos, pega os dois conjuntos e une eles. Temos todo mundo aqui rapidinho, então quando estamos trabalhando com conjuntos e operações de conjuntos, a gente utiliza o elemento ou para fazer esse tipo de operação. Esses conjuntos possuem muitas outras operações que vamos ver daqui a pouco.

Conjuntos - Mais operações de conjuntos

Continuando com as nossas operações de conjuntos, você fala: "legal, Guilherme, se eu quiser fazer alguma operação, enviar um e-mail, fazer alguma atividade com pessoas de dois conjuntos, que estão ou em um ou em outro, tanto faz, ou nos dois, isso é a união de dois conjuntos, eu uso a operação de união que é a operação do 'ou'".

Mas e se agora eu tenho que notificar as pessoas que fizeram os dois cursos, quer dizer, fizeram o curso de Data Science e o curso de Machine Learning? Fizeram os dois cursos, isso é, é a intersecção dos conjuntos. Então eu quero quem fez o primeiro curso e o segundo curso, então é a operação de “e” com &. Fez o primeiro e fez o segundo. Qual que deveria ser o resultado? 15 fez os dois? Não. 23 fez os dois? 43 fez os dois? Não. 56 fez os dois? Sim. Então eu tenho dois elementos: o 23 e o 56, que quando eu rodar deveriam aparecer como elementos que fizeram os dois cursos.

usuarios_data_science & usuarios_machine_learning

{23, 56}

Percebeu? Em uma lista, teríamos de alguma maneira, seja através de um método da própria lista ou através de um laço nosso, passar por cada elemento verificando se aquele elemento está dentro do outro conjunto. Só que os conjuntos já fazem isso de uma maneira otimizada, então essa operação de “e”, essa operação de "ou", são feitas de forma otimizada até mesmo no ponto de vista de processamento computacional.

Claro, num conjunto de dois conjuntos de quatro elementos, não vai ser um grande peso, se isso acontece uma vez a cada minuto, não vai fazer grandes diferenças. Agora, quando você tem conjuntos grandes, ou uma operação que é repetida muitas vezes, muito frequentemente, aí pode ser que faça uma grande diferença a utilização de um algoritmo ou de outro. Vemos bastante isso nos cursos de Estrutura de Dados, aqui na Alura, nos cursos de Maratona de Programação, de Algoritmos, discutimos essas abordagens de otimização.

Beleza, usuarios_data_science e usuarios_machine_learning, aí você fala: "Guilherme, tem uma outra situação. Eu tenho uma situação em que eu queria mandar e-mail, eu queria mandar e-mail, para quem fez o curso de Data Science para falar para essas pessoas fazerem o curso de Machine Learning". Só que calma aí, se eu mandar para todo mundo de Data Science, eu vou mandar para o 15, maravilha, para o 23, que já fez o Machine Learning, para o 43, maravilha, para o 56, que já fez Machine Learning, e eu não quero.

Eu quero mandar para quem enviou, para quem fez o Data Science menos quem já fez o Machine Learning. Arranca fora essas pessoas daqui de dentro, aí você fala: mas tem algumas que estão aqui dentro que não estão ali. Não tem problema, só vai arrancar quem está aqui dentro e aqui dentro. Então vai sobrar quem está no usuario_data_science mas não está no Machine Learning. Vamos dar uma olhada?

usuarios_data_science - usuarios_machine_learning

{15, 43}

E aqui eu tenho o 15 e o 43. O 15 está em um mas não está em outro, o 43 está em um, mas não está no segundo grupo. Então são três tipos de operações de conjuntos, claro, quando a gente vê o de Data Structure na documentação, você vai ver que os conjuntos sets têm diversos tipos de operações. Tem aqui diversos tipos de operações, aqui é o exemplo mais básico deles, mas a gente pode perguntar para o conjunto: será que o usuário 15 - o usuário 15 - será que ele fez o curso de Data Science, mas não fez o curso de Machine Learning? Só ele está dentro desse conjunto aqui?

Será que está dentro desse conjunto? Então aqui é "fez Data Science mas não fez Machine Learning" com fez_ds_mas_nao_fez_ml é esse conjunto. Será que o 15 está dentro desse conjunto? Lembra do in? O in existia na lista, ia passar, por exemplo, em uma lista, implementação não ordenada, seria passa pela lista procurando o elemento. No conjunto ele pode ter uma otimização para fazer essa busca e ele retornou: sim, o 15 está lá dentro.

fez_ds_mas_nao_fez_ml = usuarios_data_science - usuarios_machine_learning
15 in fez_ds_mas_nao_fez_ml

True

Será que o 23 está lá dentro? O 23 não está lá dentro, só está o 15 e o 43. Então temos as diversas operações para trabalhar com conjuntos que podíamos trabalhar com lista de uma forma independente, não importa muito. Existem outras operações às vezes não tão comuns, por exemplo: eu quero quem fez Data Science mas não fez Machine Learning e eu quero quem fez Machine Learning mas não fez Data Science. Chamamos isso de "ou" exclusivo. Então fez isso ou isso, mas não pode ter feito os dois ao mesmo tempo. Esse é o "ou" exclusivo que seria usuarios_data_science um "ou" exclusivo, que é o chapéu, o acento circunflexo, e o usuarios_machine_learnining.

usuarios_data_science ^ usuarios_machine_learning

{13, 15, 42, 43}

Então ele vai nos retornar quatro elementos que é o 13, 15, 42 e 43, que se você reparar 13, 15, 42 e 43 aparece nos dois conjuntos mas só em um dos dois conjuntos. Então dessa maneira temos diversas operações que podemos trabalhar com os nossos conjuntos, operações de conjuntos.

Sobre o curso Python Collections parte 2: conjuntos e dicionários

O curso Python Collections parte 2: conjuntos e dicionários possui 68 minutos de vídeos, em um total de 30 atividades. Gostou? Conheça nossos outros cursos de Python em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Python acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas