Reputation: 3638
I'm trying to find a way to generate ALL possible combinations using the categories below. I need exactly one element from each of Type, Cutlery, IsWeekend
, and at least one from FoodTypes
. Within those parameters, I want to generate all possible combinations of choices.
options = {
'Type' : ['Breakfast', 'Brunch', 'Lunch', 'Dinner'],
'Cutlery': ['Knife', 'Fork'],
'IsWeekend' : ['True', 'False'],
'FoodTypes' : ['Sausage', 'Bacon', 'Eggs', 'Toast']
}
For example.
Breakfast, Knife, True, Sausage
Breakfast, Knife, True, Sausage, Bacon
....
Breakfast, Fork, False, Sasuage, Eggs, Toast
I've been playing around with itertools
using product
and combinations
, but I can't seem to get the right recipe. It's currently producing a list of products, but using only one element from each list, such as:
Breakfast, Knife, True, Sausage
Breakfast, Knife, True, Bacon
How can I extend this to cover multiple food choices?
Upvotes: 2
Views: 2900
Reputation: 1290
You can do this using itertools.combinations
like so:
from itertools import combinations
options = {
'Type': ['Breakfast', 'Brunch', 'Lunch', 'Dinner'],
'Cutlery': ['Knife', 'Fork'],
'IsWeekend' : ['True', 'False'],
'FoodTypes' : ['Sausage', 'Bacon', 'Eggs', 'Toast']
}
# get a list of all the dictionary's values
lst = [j for i in options.values() for j in i]
for i in range(len(lst)+1):
for s in combinations(lst, i): print(s)
Note: This solution computes all 2^12 combinations of the flattened list of dictionary's values and works supposing that the dictionary doesn't contain duplicate items in its values. If there are duplicates, before you enter the for
loops you can easily remove them e.g. using sets
.
Upvotes: 2
Reputation: 77910
From your examples, it appears that you want the power set of the food items, and then all combinations of one element of each other entry with that set. I include the powerset
given in the Python itertools
documentation.
from itertools import *
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
options = {
'Type' : ['Breakfast', 'Brunch', 'Lunch', 'Dinner'],
'Cutlery': ['Knife', 'Fork'],
'IsWeekend' : ['True', 'False'],
'FoodTypes' : ['Sausage', 'Bacon', 'Eggs', 'Toast']
}
menu = powerset(options['FoodTypes'])
for setting in product(
options['Type'],
options['Cutlery'],
options['IsWeekend'],
menu ):
print(setting)
Output is below; I trust that you can flatten the list and remove the empty menu item (i.e. left as an exercise for the reader).
('Breakfast', 'Knife', 'True', ())
('Breakfast', 'Knife', 'True', ('Sausage',))
('Breakfast', 'Knife', 'True', ('Bacon',))
('Breakfast', 'Knife', 'True', ('Eggs',))
('Breakfast', 'Knife', 'True', ('Toast',))
('Breakfast', 'Knife', 'True', ('Sausage', 'Bacon'))
('Breakfast', 'Knife', 'True', ('Sausage', 'Eggs'))
('Breakfast', 'Knife', 'True', ('Sausage', 'Toast'))
('Breakfast', 'Knife', 'True', ('Bacon', 'Eggs'))
('Breakfast', 'Knife', 'True', ('Bacon', 'Toast'))
('Breakfast', 'Knife', 'True', ('Eggs', 'Toast'))
('Breakfast', 'Knife', 'True', ('Sausage', 'Bacon', 'Eggs'))
('Breakfast', 'Knife', 'True', ('Sausage', 'Bacon', 'Toast'))
('Breakfast', 'Knife', 'True', ('Sausage', 'Eggs', 'Toast'))
('Breakfast', 'Knife', 'True', ('Bacon', 'Eggs', 'Toast'))
('Breakfast', 'Knife', 'True', ('Sausage', 'Bacon', 'Eggs', 'Toast'))
('Breakfast', 'Knife', 'False', ())
('Breakfast', 'Knife', 'False', ('Sausage',))
('Breakfast', 'Knife', 'False', ('Bacon',))
('Breakfast', 'Knife', 'False', ('Eggs',))
('Breakfast', 'Knife', 'False', ('Toast',))
...
('Dinner', 'Fork', 'False', ('Sausage', 'Eggs', 'Toast'))
('Dinner', 'Fork', 'False', ('Bacon', 'Eggs', 'Toast'))
('Dinner', 'Fork', 'False', ('Sausage', 'Bacon', 'Eggs', 'Toast'))
Upvotes: 3