Co

Conjuntos em Python

16 exercícios

Sobre Conjuntos

Um set é uma coleção mutável e não ordenada de objetos hashable. Os membros de um conjunto precisam ser distintos: itens duplicados não são permitidos. Eles podem conter vários tipos de dados diferentes e até estruturas aninhadas, como uma tuple de tuples, desde que todos os elementos possam ser hashed. Os conjuntos também têm uma versão imutável, o frozenset.

Os conjuntos são usados com mais frequência para remover rapidamente duplicatas de outras estruturas de dados ou agrupamentos de itens. Eles também servem para comparações eficientes quando não é preciso manter ordem nem rastrear duplicatas.

Assim como outros tipos de coleção (dicionários, listas, tuplas), os sets oferecem suporte a:

  • Iteração com for item in <set>,
  • Verificação de pertencimento com in e not in,
  • Cálculo de comprimento com len(), e
  • Cópias superficiais com copy().

sets não oferecem suporte a:

  • Indexação de qualquer tipo
  • Ordenação por classificação ou por ordem de inserção
  • Fatiamento
  • Concatenação com +

Verificar se um item pertence a um set tem complexidade de tempo constante (em média), ao contrário de verificar se ele pertence a uma list ou string, em que a complexidade de tempo cresce conforme o tamanho dos dados aumenta. Métodos como <set>.union(), <set>.intersection() ou <set>.difference() também têm complexidade de tempo constante (em média).

Construção de conjuntos

Embora os conjuntos possam ser criados de muitas maneiras diferentes, os métodos de construção mais diretos são declarar um literal de conjunto, usar o construtor da classe set (set()) e usar uma compreensão de conjunto.

Literais de conjunto

Um set pode ser escrito diretamente como um literal de conjunto, com chaves {} e vírgulas entre os elementos. Duplicatas são omitidas silenciosamente:

>>> one_element = {'➕'}
{'➕'}

>>> multiple_elements = {'➕', '🔻', '🔹', '🔆'}
{'➕', '🔻', '🔹', '🔆'}

>>> multiple_duplicates =  {'Hello!', 'Hello!', 'Hello!', 
                            '¡Hola!','Привіт!', 'こんにちは!', 
                            '¡Hola!','Привіт!', 'こんにちは!'}
{'こんにちは!', '¡Hola!', 'Hello!', 'Привіт!'}

Os literais de conjunto usam as mesmas chaves dos literais de dict, o que significa que você precisa usar set() para criar um set vazio.

O construtor de conjuntos

set() (o construtor da classe set) pode ser usado com qualquer iterable passado como argumento. Os elementos do iterable são percorridos um a um e adicionados ao set individualmente. A ordem dos elementos não é preservada e as duplicatas são omitidas silenciosamente:

# To create an empty set, the constructor must be used.
>>> no_elements = set()
set()

# The tuple is unpacked & each element is added.  
# Duplicates are removed.
>>> elements_from_tuple = set(("Parrot", "Bird", 
                               334782, "Bird", "Parrot"))
{334782, 'Bird', 'Parrot'}

# The list is unpacked & each element is added.
# Duplicates are removed.
>>> elements_from_list = set([2, 3, 2, 3, 3, 3, 5, 
                              7, 11, 7, 11, 13, 13])
{2, 3, 5, 7, 11, 13}

Compreensões de conjunto

Assim como lists e dicts, os conjuntos podem ser criados por meio de uma compreensão:

# First, a list with duplicates
>>> numbers = [1,2,3,4,5,6,6,5,4,8,9,9,9,2,3,12,18]

# This set comprehension squares the numbers divisible by 3
# Duplicates are removed.
>>> calculated = {item**2 for item in numbers if item % 3 == 0}
{9, 36, 81, 144, 324}

Cuidados ao criar conjuntos

Por causa do comportamento de "desempacotamento", usar o construtor set com uma string pode causar surpresas:

# String elements (Unicode code points) are 
# iterated through and added *individually*.
>>> elements_string = set("Timbuktu")
{'T', 'b', 'i', 'k', 'm', 't', 'u'}

# Unicode separators and positioning code points 
# are also added *individually*.
>>> multiple_code_points_string = set('अभ्यास')
{'अ', 'भ', 'य', 'स', 'ा', '्'}

Lembre-se: os conjuntos podem conter tipos de dados diferentes e tipos de dados aninhados, mas todos os elementos de um set precisam ser hashable:

# Attempting to use a list for a set member throws a TypeError
>>> lists_as_elements = {['🌈','💦'], 
                        ['☁️','⭐️','🌍'], 
                        ['⛵️', '🚲', '🚀']}

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


# Standard sets are mutable, so they cannot be hashed.
>>> sets_as_elements = {{'🌈','💦'}, 
                        {'☁️','⭐️','🌍'}, 
                        {'⛵️', '🚲', '🚀'}}

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'

No entanto, um set de sets pode ser criado com o tipo frozenset():

# Frozensets don't have a literal form.
>>> set_1 = frozenset({'🌈','💦'})
>>> set_2 = frozenset({'☁️','⭐️','🌍'})
>>> set_3 = frozenset({'⛵️', '🚲', '🚀'})

>>> frozen_sets_as_elements = {set_1, set_2, set_3}
>>> frozen_sets_as_elements
{frozenset({'⛵️', '🚀', '🚲'}),
 frozenset({'🌈', '💦'}),
 frozenset({'☁️', '⭐️', '🌍'})}

Adicionar e remover membros de um conjunto

É possível adicionar ou remover elementos de um set com os métodos <set>.add(<item>) e <set>.remove(<item>). O método .remove(<item>) lança um KeyError se o item não estiver presente no set:

>>> creatures = {'crow', 'duck', 'fish', 'monkey', 'elephant'}
>>> creatures.add('beaver')
>>> creatures.remove('duck')
>>> creatures
{'beaver', 'crow', 'elephant', 'fish', 'monkey'}

# Trying to remove an item that is not present raises a KeyError
>>> creatures.remove('bear')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  KeyError: 'bear'

Outras formas de remover membros de um conjunto

  • <set>.discard(<item>) remove um item do set, mas não lança um KeyError se o item não estiver presente.
  • <set>.clear() remove todos os itens do conjunto.
  • <set>.pop() remove e retorna um item arbitrário, e lança um KeyError se o set estiver vazio.

Operações com conjuntos

Os conjuntos têm métodos que, em geral, imitam as operações matemáticas com conjuntos. A maioria desses métodos (não todos) tem um operador equivalente. Os métodos geralmente aceitam qualquer iterable como argumento, enquanto os operadores exigem que os dois lados da operação sejam sets ou frozensets.

Testar pertencimento entre conjuntos

O método <set>.isdisjoint(<other_collection>) serve para testar se os elementos de um set têm alguma sobreposição com os elementos de outro. O método aceita qualquer iterable ou set como argumento. Ele retorna True se os dois conjuntos não tiverem nenhum elemento em comum, e False se houver elementos compartilhados.

# Both mammals and additional_animals are lists.
>>> mammals = ['squirrel','dog','cat','cow', 'tiger', 'elephant']
>>> additional_animals = ['pangolin', 'panda', 'parrot', 
                          'lemur', 'tiger', 'pangolin']

# Animals is a dict.
>>> animals = {'chicken': 'white',
               'sparrow': 'grey',
               'eagle': 'brown and white',
               'albatross': 'grey and white',
               'crow': 'black',
               'elephant': 'grey', 
               'dog': 'rust',
               'cow': 'black and white',
               'tiger': 'orange and black',
               'cat': 'grey',
               'squirrel': 'black'}
               
# Birds is a set.
>>> birds = {'crow','sparrow','eagle','chicken', 'albatross'}

# Mammals and birds don't share any elements.
>>> birds.isdisjoint(mammals)
True

# There are also no shared elements between 
# additional_animals and birds.
>>> birds.isdisjoint(additional_animals)
True

# Animals and mammals have shared elements.
# **Note** The first object needs to be a set or converted to a set
# since .isdisjoint() is a set method.
>>> set(animals).isdisjoint(mammals)
False

Verificar subconjuntos e superconjuntos

<set>.issubset(<other_collection>) serve para verificar se todo elemento de <set> também está em <other_collection>. A forma com operador é <set> <= <other_set>:

# Set methods will take any iterable as an argument.
# All members of birds are also members of animals.
>>> birds.issubset(animals)
True

# All members of mammals also appear in animals.
# **Note** The first object needs to be a set or converted to a set
# since .issubset() is a set method.
>>> set(mammals).issubset(animals)
True

# Both objects need to be sets to use a set operator
>>> birds <= set(mammals)
False

# A set is always a loose subset of itself.
>>> set(additional_animals) <= set(additional_animals)
True

<set>.issuperset(<other_collection>) é o inverso de .issubset(). Ele serve para verificar se todo elemento de <other_collection> também está em <set>. A forma com operador é <set> >= <other_set>:

# All members of mammals also appear in animals.
# **Note** The first object needs to be a set or converted to a set
# since .issuperset() is a set method.
>>> set(animals).issuperset(mammals)
True

# All members of animals do not show up as members of birds.
>>> birds.issuperset(animals)
False

# Both objects need to be sets to use a set operator
>>> birds >= set(mammals)
False

# A set is always a loose superset of itself.
>>> set(animals) >= set(animals)
True

Subconjuntos e superconjuntos 'próprios'

<set> < <other_set> e <set> > <other_set> são usados para testar subconjuntos próprios. Um set é um subconjunto próprio se (<set> <= <other_set>) E (<set> != <other_set>) para o operador <.

Um set é um superconjunto próprio se (<set> >= <other_set>) E (<set> != <other_set>) para o operador >. Esses operadores não têm método equivalente:

>>> animal_names = {'albatross','cat','chicken','cow','crow','dog',
                   'eagle','elephant','sparrow','squirrel','tiger'}

>>> animals_also = {'albatross','cat','chicken','cow','crow','dog',
                   'eagle','elephant','sparrow','squirrel','tiger'}

>>> mammals = {'squirrel','dog','cat','cow', 'tiger', 'elephant'}
>>> birds   = {'crow','sparrow','eagle','chicken', 'albatross'}

>>> mammals < animal_names
True

>>> animal_names > birds
True

# A set is not a *proper subset* if set == other set.
>>> animals_also < animal_names
False

# A set is never a *proper subset* of itself
>>> animals_also < animals_also
False

União de conjuntos

<set>.union(*<other iterables>) retorna um novo set com os elementos de <set> e de todos os <other iterables>. A forma com operador desse método é <set> | <other set 1> | <other set 2> | ... | <other set n>.

>>> perennials = {'Asparagus', 'Broccoli', 'Sweet Potato', 'Kale'}
>>> annuals = {'Corn', 'Zucchini', 'Sweet Peas', 'Summer Squash'}
>>> more_perennials = ['Radicchio', 'Rhubarb', 
                      'Spinach', 'Watercress']

# Methods will take any iterable as an argument.
>>> perennials.union(more_perennials)
{'Asparagus','Broccoli','Kale','Radicchio','Rhubarb',
'Spinach','Sweet Potato','Watercress'}

# Operators require sets.
>>> set(more_perennials) | perennials
{'Asparagus',
 'Broccoli',
 'Kale',
 'Radicchio',
 'Rhubarb',
 'Spinach',
 'Sweet Potato',
 'Watercress'}

Diferença de conjuntos

<set>.difference(*<other iterables>) retorna um novo set com os elementos do <set> original que não estão em <others>. A versão com operador desse método é <set> - <other set 1> - <other set 2> - ... - <other set n>.

>>> berries_and_veggies = {'Asparagus', 
                          'Broccoli', 
                          'Watercress', 
                          'Goji Berries', 
                          'Goose Berries', 
                          'Ramps', 
                          'Walking Onions', 
                          'Blackberries', 
                          'Strawberries', 
                          'Rhubarb', 
                          'Kale', 
                          'Artichokes', 
                          'Currants'}

>>> veggies = ('Asparagus', 'Broccoli', 'Watercress', 'Ramps',
               'Walking Onions', 'Rhubarb', 'Kale', 'Artichokes')

# Methods will take any iterable as an argument.
>>> berries = berries_and_veggies.difference(veggies)
{'Blackberries','Currants','Goji Berries',
 'Goose Berries', 'Strawberries'}

# Operators require sets.
>>> berries_and_veggies - berries
{'Artichokes','Asparagus','Broccoli','Kale',
'Ramps','Rhubarb','Walking Onions','Watercress'}

Interseção de conjuntos

<set>.intersection(*<other iterables>) retorna um novo set com os elementos comuns ao set original e a todos os <others> (em outras palavras, o set em que tudo se intersecta). A versão com operador desse método é <set> & <other set> & <other set 2> & ... & <other set n>

>>> perennials = {'Annatto','Asafetida','Asparagus','Azalea',
                 'Winter Savory', 'Broccoli','Curry Leaf','Fennel', 
                 'Kaffir Lime','Kale','Lavender','Mint','Oranges',
                 'Oregano', 'Tarragon', 'Wild Bergamot'}

>>> annuals = {'Corn', 'Zucchini', 'Sweet Peas', 'Marjoram', 
              'Summer Squash', 'Okra','Shallots', 'Basil', 
              'Cilantro', 'Cumin', 'Sunflower', 'Chervil', 
              'Summer Savory'}

>>> herbs = ['Annatto','Asafetida','Basil','Chervil','Cilantro',
            'Curry Leaf','Fennel','Kaffir Lime','Lavender',
            'Marjoram','Mint','Oregano','Summer Savory', 
            'Tarragon','Wild Bergamot','Wild Celery',
            'Winter Savory']


# Methods will take any iterable as an argument.
>>> perennial_herbs = perennials.intersection(herbs)
{'Annatto', 'Asafetida', 'Curry Leaf', 'Fennel', 'Kaffir Lime',
 'Lavender', 'Mint', 'Oregano', 'Wild Bergamot','Winter Savory'}

# Operators require both groups be sets.
>>> annuals & set(herbs)
 {'Basil', 'Chervil', 'Marjoram', 'Cilantro'}

Diferença simétrica entre conjuntos

<set>.symmetric_difference(<other iterable>) retorna um novo set que contém os elementos que estão em <set> OU em <other>, mas não nos dois. A versão com operador desse método é <set> ^ <other set>.

>>> plants_1 = {'🌲','🍈','🌵', '🥑','🌴', '🥭'}
>>> plants_2 = ('🌸','🌴', '🌺', '🌲', '🌻', '🌵')


# Methods will take any iterable as an argument.
>>> fruit_and_flowers = plants_1.symmetric_difference(plants_2)
>>> fruit_and_flowers
{'🌸', '🌺', '🍈', '🥑', '🥭','🌻' }


# Operators require both groups be sets.
>>> fruit_and_flowers ^ plants_1
{'🌲',  '🌸', '🌴', '🌵','🌺', '🌻'}

>>> fruit_and_flowers ^ set(plants_2)
{'🥭', '🌴', '🌵', '🍈', '🌲', '🥑'}
Note

Uma diferença simétrica de mais de dois conjuntos resulta em um set que inclui tanto os elementos exclusivos de cada set quanto os elementos compartilhados entre mais de dois conjuntos da série (detalhes no artigo da Wikipédia sobre diferença simétrica).

Para obter apenas os itens exclusivos de cada set da série, as interseções entre todas as combinações de 2 conjuntos precisam ser reunidas em uma etapa separada e removidas:

>>> one = {'black pepper','breadcrumbs','celeriac','chickpea flour',
           'flour','lemon','parsley','salt','soy sauce',
           'sunflower oil','water'}

>>> two = {'black pepper','cornstarch','garlic','ginger',
           'lemon juice','lemon zest','salt','soy sauce','sugar',
           'tofu','vegetable oil','vegetable stock','water'}

>>> three = {'black pepper','garlic','lemon juice','mixed herbs',
             'nutritional yeast', 'olive oil','salt','silken tofu',
             'smoked tofu','soy sauce','spaghetti','turmeric'}

>>> four = {'barley malt','bell pepper','cashews','flour',
            'fresh basil','garlic','garlic powder', 'honey',
            'mushrooms','nutritional yeast','olive oil','oregano',
            'red onion', 'red pepper flakes','rosemary','salt',
            'sugar','tomatoes','water','yeast'}

>>> intersections = (one & two | one & three | one & four | 
                     two & three | two & four | three & four)
...
{'black pepper','flour','garlic','lemon juice','nutritional yeast', 
'olive oil','salt','soy sauce', 'sugar','water'}

# The ^ operation will include some of the items in intersections, 
# which means it is not a "clean" symmetric difference - there
# are overlapping members.
>>> (one ^ two ^ three ^ four) & intersections
{'black pepper', 'garlic', 'soy sauce', 'water'}

# Overlapping members need to be removed in a separate step
# when there are more than two sets that need symmetric difference.
>>> (one ^ two ^ three ^ four) - intersections
...
{'barley malt','bell pepper','breadcrumbs', 'cashews','celeriac',
  'chickpea flour','cornstarch','fresh basil', 'garlic powder',
  'ginger','honey','lemon','lemon zest','mixed herbs','mushrooms',
  'oregano','parsley','red onion','red pepper flakes','rosemary',
  'silken tofu','smoked tofu','spaghetti','sunflower oil', 'tofu', 
  'tomatoes','turmeric','vegetable oil','vegetable stock','yeast'}
Editar via GitHub O link abre em uma nova janela ou aba

Aprenda Conjuntos

A prática está bloqueada

Desbloqueie mais 4 exercícios para praticar Conjuntos