2

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?

2
  • 3
    You haven't made it clear which combinations you want out of the myriad possibilities. Your examples show one item from each of the first three lists, but unspecified combinations (permutations?) of the last one. Please be careful with your terminology, as your examples seem to be quite incomplete for the terms you've used. Commented Aug 30, 2018 at 16:10
  • Yes, I apologise for the somewhat vague terms used, but I found it difficult to articulate, exactly what I was trying to achieve. Commented Aug 30, 2018 at 16:54

2 Answers 2

3

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'))
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, that's exactly what I'm looking for. Thank you!
2

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.

2 Comments

This prints all 2^12 combinations of the combined, flattened list of items. I'm doubtful (but not sure) that this is what OP wants.
@Prune Yes I know, I think that's what the OP wants if I understood well from the OP's description (I might be wrong though)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.