Um conjunto é 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 seja possível calcular o hash de todos os elementos.
Os conjuntos também vêm em uma versão imutável, os frozensets.
Os conjuntos são usados com mais frequência para remover duplicatas rapidamente de outras estruturas de dados ou agrupamentos de itens. Também são usados para comparações eficientes quando sequenciamento e rastreamento de duplicatas não são necessários.
Assim como outros tipos de coleção (dicionários, listas, tuplas), sets oferecem suporte a:
for item in <set>
in e not in,len(), ecopy()
sets não oferecem suporte a:
+
Verificar se um elemento 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 comprimento dos dados aumenta.
Métodos como <set>.union(), <set>.intersection() ou <set>.difference() também têm complexidade de tempo constante (em média).
Um set pode ser escrito diretamente como um literal de conjunto, usando 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 que os literais dict, o que significa que você precisa usar set() para criar um set vazio.
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}
Por causa do comportamento de "desempacotamento", usar set() com uma string pode ser surpreendente:
# 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('अभ्यास')
{'अ', 'भ', 'य', 'स', 'ा', '्'}
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'
Os conjuntos têm métodos que, em geral, imitam as operações matemáticas de conjuntos.
A maioria (não todos) desses métodos tem um operador equivalente.
Em geral, os métodos aceitam qualquer iterable como argumento, enquanto os operadores exigem que ambos os lados da operação sejam sets ou frozensets.
O método <set>.isdisjoint(<other_collection>) é usado para testar se os elementos de um set têm alguma sobreposição com os elementos de outro set.
O método aceita qualquer iterable ou set como argumento.
Retorna True se os dois conjuntos não tiverem nenhum elemento em comum e False se houver elementos compartilhados.
Não há operador equivalente:
# 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
<set>.issubset(<other_collection>) é usado para verificar se todo elemento de <set> também está em <other_collection>.
A forma com operador é <set> <= <other_set>:
# 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'}
# 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().
É usado 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
<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'}
<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'}
<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'}
<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 em ambos.
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)
{'🥭', '🌴', '🌵', '🍈', '🌲', '🥑'}
A 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, é preciso agregar as interseções entre todas as combinações de dois conjuntos em uma etapa separada e removê-las:
>>> 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'}
Você e seus sócios administram uma pequena empresa de catering. Vocês acabaram de aceitar organizar um evento para um clube de culinária local que apresenta pratos "favoritos do clube". O clube tem pouca experiência em sediar eventos grandes e precisa de ajuda para organizar, comprar, preparar e servir. Você decidiu escrever alguns pequenos scripts em Python para acelerar todo o processo de planejamento.
As receitas do evento foram adicionadas de várias fontes e seus ingredientes parecem ter entradas duplicadas (ou mais). Você não quer acabar comprando itens em excesso! Antes que as compras e o cozimento possam começar, a lista de ingredientes de cada prato precisa ser "limpa".
Implemente a função clean_ingredients(<dish_name>, <dish_ingredients>), que recebe o nome de um prato e uma list de ingredientes.
Essa função deve retornar uma tuple com o nome do prato como primeiro item, seguida do set de ingredientes sem duplicatas.
>>> clean_ingredients('Punjabi-Style Chole', ['onions', 'tomatoes', 'ginger paste', 'garlic paste', 'ginger paste', 'vegetable oil', 'bay leaves', 'cloves', 'cardamom', 'cilantro', 'peppercorns', 'cumin powder', 'chickpeas', 'coriander powder', 'red chili powder', 'ground turmeric', 'garam masala', 'chickpeas', 'ginger', 'cilantro'])
>>> ('Punjabi-Style Chole', {'garam masala', 'bay leaves', 'ground turmeric', 'ginger', 'garlic paste', 'peppercorns', 'ginger paste', 'red chili powder', 'cardamom', 'chickpeas', 'cumin powder', 'vegetable oil', 'tomatoes', 'coriander powder', 'onions', 'cilantro', 'cloves'})
O evento vai incluir tanto coquetéis quanto "mocktails", bebidas mistas sem álcool. Você precisa garantir que as bebidas "mocktail" sejam realmente sem álcool e que os coquetéis de fato contenham álcool.
Implemente a função check_drinks(<drink_name>, <drink_ingredients>), que recebe o nome de uma bebida e uma list de ingredientes.
A função deve retornar o nome da bebida seguido de "Mocktail" se a bebida não tiver ingredientes alcoólicos, e o nome da bebida seguido de "Cocktail" se a bebida contiver álcool.
Para os fins deste exercício, os coquetéis incluirão apenas álcoois da constante ALCOHOLS em sets_categories_data.py:
>>> from sets_categories_data import ALCOHOLS
>>> check_drinks('Honeydew Cucumber', ['honeydew', 'coconut water', 'mint leaves', 'lime juice', 'salt', 'english cucumber'])
...
'Honeydew Cucumber Mocktail'
>>> check_drinks('Shirley Tonic', ['cinnamon stick', 'scotch', 'whole cloves', 'ginger', 'pomegranate juice', 'sugar', 'club soda'])
...
'Shirley Tonic Cocktail'
A lista de convidados inclui pessoas com necessidades alimentares diferentes, e sua equipe vai precisar separar os pratos em Vegan, Vegetarian, Paleo, Keto e Omnivore. Um prato pertence a uma categoria somente se todos os seus ingredientes aparecerem no conjunto de ingredientes da categoria.
Implemente a função categorize_dish(<dish_name>, <dish_ingredients>), que recebe o nome de um prato e um set com os ingredientes desse prato.
A função deve retornar uma string com o formato dish name: <CATEGORY> (a qual categoria de refeição o prato pertence).
Todos os pratos fornecidos vão "se encaixar" em uma das categorias importadas de sets_categories_data.py (VEGAN, VEGETARIAN, PALEO, KETO ou OMNIVORE).
>>> from sets_categories_data import VEGAN, VEGETARIAN, PALEO, KETO, OMNIVORE
>>> categorize_dish('Sticky Lemon Tofu', {'tofu', 'soy sauce', 'salt', 'black pepper', 'cornstarch', 'vegetable oil', 'garlic', 'ginger', 'water', 'vegetable stock', 'lemon juice', 'lemon zest', 'sugar'})
...
'Sticky Lemon Tofu: VEGAN'
>>> categorize_dish('Shrimp Bacon and Crispy Chickpea Tacos with Salsa de Guacamole', {'shrimp', 'bacon', 'avocado', 'chickpeas', 'fresh tortillas', 'sea salt', 'guajillo chile', 'slivered almonds', 'olive oil', 'butter', 'black pepper', 'garlic', 'onion'})
...
'Shrimp Bacon and Crispy Chickpea Tacos with Salsa de Guacamole: OMNIVORE'
Alguns convidados têm alergias e restrições alimentares adicionais. Esses ingredientes precisam ser marcados/anotados em cada prato para que não causem problemas.
Implemente a função tag_special_ingredients(<dish>), que recebe uma tuple com o nome do prato na primeira posição e uma list ou set de ingredientes desse prato na segunda posição.
Retorne o nome do prato seguido do set de ingredientes que exigem uma observação especial na descrição do prato.
Os ingredientes de um prato dentro de uma list podem ou não ter duplicatas.
Para os fins deste exercício, todos os alérgenos ou ingredientes especiais que precisam ser rotulados estão na constante SPECIAL_INGREDIENTS importada de sets_categories_data.py.
>>> from sets_categories_data import SPECIAL_INGREDIENTS
>>> tag_special_ingredients(('Ginger Glazed Tofu Cutlets', ['tofu', 'soy sauce', 'ginger', 'corn starch', 'garlic', 'brown sugar', 'sesame seeds', 'lemon juice']))
...
('Ginger Glazed Tofu Cutlets', {'garlic','soy sauce','tofu'})
>>> tag_special_ingredients(('Arugula and Roasted Pork Salad', ['pork tenderloin', 'arugula', 'pears', 'blue cheese', 'pine nuts', 'balsamic vinegar', 'onions', 'black pepper']))
...
('Arugula and Roasted Pork Salad', {'pork tenderloin', 'blue cheese', 'pine nuts', 'onions'})
Como preparação para fazer os pedidos e as compras, você vai precisar compilar uma "lista mestra" de ingredientes para tudo o que está no menu (quantidades a serem preenchidas depois).
Implemente a função compile_ingredients(<dishes>), que recebe uma list de pratos e retorna um conjunto com todos os ingredientes de todos os pratos listados.
Cada prato individual é representado pelo seu set de ingredientes.
dishes = [ {'tofu', 'soy sauce', 'ginger', 'corn starch', 'garlic', 'brown sugar', 'sesame seeds', 'lemon juice'},
{'pork tenderloin', 'arugula', 'pears', 'blue cheese', 'pine nuts',
'balsamic vinegar', 'onions', 'black pepper'},
{'honeydew', 'coconut water', 'mint leaves', 'lime juice', 'salt', 'english cucumber'}]
>>> compile_ingredients(dishes)
...
{'arugula', 'brown sugar', 'honeydew', 'coconut water', 'english cucumber', 'balsamic vinegar', 'mint leaves', 'pears', 'pork tenderloin', 'ginger', 'blue cheese', 'soy sauce', 'sesame seeds', 'black pepper', 'garlic', 'lime juice', 'corn starch', 'pine nuts', 'lemon juice', 'onions', 'salt', 'tofu'}
Os anfitriões lhe deram uma lista de pratos que gostariam que fossem preparados como aperitivos "de uma mordida" para serem servidos em bandejas. Você precisa separá-los da lista principal de pratos que estão sendo preparados em porções maiores.
Implemente a função separate_appetizers(<dishes>, <appetizers>), que recebe uma list de nomes de pratos e uma list de nomes de aperitivos.
A função deve retornar a list de nomes de pratos sem os nomes dos aperitivos.
A list de <dishes> ou a de <appetizers> pode conter duplicatas e talvez precise ser desduplicada.
dishes = ['Avocado Deviled Eggs','Flank Steak with Chimichurri and Asparagus', 'Kingfish Lettuce Cups',
'Grilled Flank Steak with Caesar Salad','Vegetarian Khoresh Bademjan','Avocado Deviled Eggs',
'Barley Risotto','Kingfish Lettuce Cups']
appetizers = ['Kingfish Lettuce Cups','Avocado Deviled Eggs','Satay Steak Skewers',
'Dahi Puri with Black Chickpeas','Avocado Deviled Eggs','Asparagus Puffs',
'Asparagus Puffs']
>>> separate_appetizers(dishes, appetizers)
...
['Vegetarian Khoresh Bademjan', 'Barley Risotto', 'Flank Steak with Chimichurri and Asparagus',
'Grilled Flank Steak with Caesar Salad']
Em cada categoria (Vegan, Vegetarian, Paleo, Keto, Omnivore), você vai separar os ingredientes que aparecem em apenas um prato. Esses ingredientes "singleton" serão atribuídos a um comprador especial para garantir que não sejam esquecidos na correria de fazer todo o resto.
Implemente a função singleton_ingredients(<dishes>, <INTERSECTIONS>), que recebe uma list de pratos e uma constante <CATEGORY>_INTERSECTIONS da mesma categoria.
Cada prato é representado por um set dos seus ingredientes.
Cada <CATEGORY>_INTERSECTIONS é um set de ingredientes que aparecem em mais de um prato da categoria.
Usando operações de conjunto, sua função deve retornar um set de ingredientes "singleton" (ingredientes que aparecem em apenas um prato da categoria).
from sets_categories_data import example_dishes, EXAMPLE_INTERSECTION
>>> singleton_ingredients(example_dishes, EXAMPLE_INTERSECTION)
...
{'garlic powder', 'sunflower oil', 'mixed herbs', 'cornstarch', 'celeriac', 'honey', 'mushrooms', 'bell pepper', 'rosemary', 'parsley', 'lemon', 'yeast', 'vegetable oil', 'vegetable stock', 'silken tofu', 'tofu', 'cashews', 'lemon zest', 'smoked tofu', 'spaghetti', 'ginger', 'breadcrumbs', 'tomatoes', 'barley malt', 'red pepper flakes', 'oregano', 'red onion', 'fresh basil'}
Crie sua conta no Exercism para aprender e dominar Python com 17 conceitos146 exercícios e mentoria humana de verdade, tudo de graça.