집합은 변경 가능하고 순서가 없는 해시 가능한 객체들의 컬렉션이에요.
집합의 원소는 서로 달라야 해요. 중복된 항목은 허용되지 않아요.
여러 가지 서로 다른 데이터 타입은 물론, tuple의 tuples처럼 중첩된 구조까지 담을 수 있어요. 단, 모든 원소가 _해시 가능_해야 해요.
집합에는 변경할 수 없는 frozensets 형태도 있어요.
집합은 다른 데이터 구조나 항목 그룹에서 중복을 빠르게 제거할 때 가장 흔히 사용해요. 순서 지정과 중복 추적이 필요하지 않을 때는 효율적으로 비교하는 데에도 사용해요.
다른 컬렉션 타입(딕셔너리, 배열, 튜플)처럼 sets은 다음을 지원해요:
for item in <set>를 통한 반복in과 not in을 통한 멤버십 확인len()을 통한 길이 계산copy()를 통한 얕은 복사sets은 다음을 지원하지 않아요:
+를 통한 연결set에서 멤버십을 확인하는 것은 평균적으로 상수 시간 복잡도를 가져요. 반면 list나 string에서 멤버십을 확인하는 경우에는 데이터 길이가 길어질수록 시간 복잡도도 커져요.
<set>.union(), <set>.intersection(), <set>.difference() 같은 메서드도 평균적으로 상수 시간 복잡도를 가져요.
set은 중괄호 {}와 원소 사이의 쉼표를 사용해 _집합 리터럴_로 직접 입력할 수 있어요.
중복은 조용히 생략돼요:
>>> one_element = {'➕'}
{'➕'}
>>> multiple_elements = {'➕', '🔻', '🔹', '🔆'}
{'➕', '🔻', '🔹', '🔆'}
>>> multiple_duplicates = {'Hello!', 'Hello!', 'Hello!',
'¡Hola!','Привіт!', 'こんにちは!',
'¡Hola!','Привіт!', 'こんにちは!'}
{'こんにちは!', '¡Hola!', 'Hello!', 'Привіт!'}
집합 리터럴은 dict 리터럴과 같은 중괄호를 사용해요. 따라서 빈 set을 만들려면 set()을 사용해야 해요.
set()(즉 set 클래스의 생성자)은 인자로 전달된 모든 iterable과 함께 사용할 수 있어요.
iterable의 원소들은 하나씩 순회하면서 set에 개별적으로 추가돼요.
원소 순서는 유지되지 않고 중복은 조용히 생략돼요:
# 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}
"언패킹" 동작 때문에 set()에 문자열을 사용하면 놀랄 수 있어요:
# 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('अभ्यास')
{'अ', 'भ', 'य', 'स', 'ा', '्'}
집합은 서로 다른 데이터 타입과 중첩된 데이터 타입을 담을 수 있지만, 모든 set 원소는 _해시 가능_해야 해요:
# 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'
집합에는 일반적으로 수학적 집합 연산을 흉내 내는 메서드들이 있어요.
이런 메서드 대부분(전부는 아니에요)에는 연산자 형태가 있어요.
메서드는 보통 모든 iterable을 인자로 받지만, 연산자는 연산 양쪽이 모두 set이나 frozensets이어야 해요.
<set>.isdisjoint(<other_collection>) 메서드는 한 set의 원소가 다른 set의 원소와 겹치는지 확인할 때 사용해요.
이 메서드는 모든 iterable이나 set을 인자로 받아요.
두 집합이 공통 원소를 하나도 가지지 않으면 True를, 원소를 공유하면 False를 반환해요.
이에 해당하는 연산자 형태는 없어요:
# 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>)는 <set>의 모든 원소가 <other_collection>에도 있는지 확인할 때 사용해요.
연산자 형태는 <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>)는 .issubset()의 반대예요.
<other_collection>의 모든 원소가 <set>에도 있는지 확인할 때 사용해요.
연산자 형태는 <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>)는 원래 set과 모든 <others>에 공통으로 있는 원소로 이루어진 새 set을 반환해요(즉, 모든 것이 교차하는 set이에요).
이 메서드의 연산자 버전은 <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>)는 <set>과 모든 <other iterables>의 원소로 이루어진 새 set을 반환해요.
이 메서드의 연산자 형태는 <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>)는 원래 <set>에 있지만 <others>에는 없는 원소로 이루어진 새 set을 반환해요.
이 메서드의 연산자 버전은 <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>)는 <set> 또는 <other>에 있지만 둘 다에는 없는 원소를 담은 새 set을 반환해요.
이 메서드의 연산자 버전은 <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)
{'🥭', '🌴', '🌵', '🍈', '🌲', '🥑'}
세 개 이상 집합의 대칭 차집합을 구하면, 각 set에 고유한 원소와 계열 내 세 개 이상의 집합 사이에서 공유되는 원소를 모두 포함하는 sets이 나와요(자세한 내용은 대칭 차집합에 관한 위키백과 문서를 참고해요).
계열에서 각 sets에 고유한 항목만 얻으려면, 가능한 모든 두 집합 조합 사이의 교집합을 별도의 단계에서 모아서 제거해야 해요:
>>> 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'}
비즈니스 파트너들과 함께 작은 케이터링 회사를 운영하고 있어요. 최근에는 지역 요리 동호회의 행사를 맡기로 했는데, 이 행사에서는 동호회 회원들이 가장 좋아하는 요리들을 선보일 예정이에요. 이 동호회는 큰 행사를 주최해 본 경험이 없어서 준비, 장보기, 손질, 서빙 전반에 도움이 필요해요. 그래서 전체 준비 과정을 빠르게 진행하기 위해 작은 Python 스크립트 몇 개를 작성하기로 했어요.
행사에 쓸 레시피는 여러 출처에서 가져온 터라 재료 목록에 중복된(또는 그 이상의) 항목이 있는 것 같아요. 재료를 필요 이상으로 사들이고 싶지는 않겠죠! 장보기와 요리를 시작하기 전에, 각 요리의 재료 목록을 먼저 "정리"해야 해요.
요리 이름과 재료 list를 받는 clean_ingredients(<dish_name>, <dish_ingredients>) 함수를 구현해요. 이 함수는 첫 번째 항목으로 요리 이름을, 그다음으로 중복을 제거한 재료 set을 담은 tuple을 반환해야 해요.
>>> 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'})
이번 행사에서는 칵테일과 함께 "mocktails", 즉 알코올이 들어가지 않은 혼합 음료도 선보일 거예요. "mocktail" 음료에는 정말로 알코올이 들어 있지 않은지, 그리고 칵테일에는 정말로 알코올이 들어 있는지 확인해야 해요.
음료 이름과 재료 list를 받는 check_drinks(<drink_name>, <drink_ingredients>) 함수를 구현해요. 이 함수는 알코올 재료가 없으면 음료 이름 뒤에 "Mocktail"을 붙여서 반환하고, 알코올이 들어 있으면 음료 이름 뒤에 "Cocktail"을 붙여서 반환해야 해요. 이 연습 문제에서는 칵테일에 sets_categories_data.py의 ALCOHOLS 상수에 있는 알코올만 포함된다고 가정해요.
>>> 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'
초대 손님 명단에는 식이 요구 사항이 각기 다른 사람들이 있어서, 직원들이 요리를 Vegan, Vegetarian, Paleo, Keto, Omnivore로 나눠야 해요. 어떤 요리는 재료가 모두 해당 카테고리의 재료 집합에 들어 있을 때에만 그 카테고리에 속해요.
요리 이름과 그 요리의 재료 set을 받는 categorize_dish(<dish_name>, <dish_ingredients>) 함수를 구현해요. 이 함수는 dish name: <CATEGORY> 형태의 문자열을 반환해야 해요(요리가 어느 식사 카테고리에 속하는지). 주어지는 모든 요리는 sets_categories_data.py에서 가져온 카테고리(VEGAN, VEGETARIAN, PALEO, KETO, 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'
일부 손님은 알레르기가 있거나 추가적인 식이 제한이 있어요. 이런 재료는 문제를 일으키지 않도록 각 요리마다 태그를 달거나 주석을 남겨야 해요.
첫 번째 위치에 요리 이름이, 두 번째 위치에 그 요리의 재료 list 또는 set이 담긴 tuple을 받는 tag_special_ingredients(<dish>) 함수를 구현해요. 요리 이름과 함께, 요리 설명에 특별한 메모가 필요한 재료들의 set을 반환해요. list 안의 요리 재료에는 중복이 있을 수도 있고 없을 수도 있어요. 이 연습 문제에서는 라벨을 붙여야 하는 모든 알레르기 유발 재료나 특수 재료가 sets_categories_data.py에서 가져온 SPECIAL_INGREDIENTS 상수에 들어 있어요.
>>> 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'})
주문과 장보기를 준비하려면, 메뉴에 있는 모든 요리의 재료를 모은 "마스터 목록"을 만들어야 해요(수량은 나중에 채워 넣어요).
요리들의 list를 받아, 나열된 모든 요리의 재료 전체를 담은 집합을 반환하는 compile_ingredients(<dishes>) 함수를 구현해요. 각 요리는 자기 재료들의 set으로 표현돼요.
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'}
주최자들이 쟁반에 내놓을 "한입 크기" 애피타이저로 준비해 달라고 요청한 요리 목록을 건네줬어요. 이 요리들은 더 큰 접시로 준비하는 메인 요리 목록에서 빼내야 해요.
요리 이름 list와 애피타이저 이름 list를 받는 separate_appetizers(<dishes>, <appetizers>) 함수를 구현해요. 이 함수는 애피타이저 이름을 제거한 요리 이름 list를 반환해야 해요. <dishes>나 <appetizers> list 중 어느 쪽에든 중복이 있을 수 있고, 중복을 제거해야 할 수도 있어요.
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']
각 카테고리(Vegan, Vegetarian, Paleo, Keto, Omnivore) 안에서, 요리 하나에만 들어가는 재료를 골라낼 거예요. 이런 "싱글턴" 재료에는 전담 장보기 담당자를 배정해서, 다른 재료를 사느라 정신없는 와중에도 빠뜨리지 않도록 할 거예요.
요리 list와 같은 카테고리의 <CATEGORY>_INTERSECTIONS 상수를 받는 singleton_ingredients(<dishes>, <INTERSECTIONS>) 함수를 구현해요. 각 요리는 자기 재료들의 set으로 표현돼요. 각 <CATEGORY>_INTERSECTIONS는 해당 카테고리에서 요리 하나 이상에 들어가는 재료들의 set이에요. 집합 연산을 사용해서, "싱글턴" 재료(카테고리에서 요리 하나에만 들어가는 재료)들의 set을 반환해야 해요.
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'}
Exercism에 가입하고 Python 트랙을 개념 17개연습 문제 146개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.