Slicing a nested dictionary

Just wondering if it’s possible to slice a nested dictionary. For example, is there a way I can print only the first 4 items in the dictionary below ( “Ham & Cheese”, “Cheesy Garlic”, “Hawaiian”, “Classic Cheese”.

MENU = {1 : {"Ham & Cheese" : 5},
        2 : {"Cheesy Garlic" : 5},
        3 : {"Hawaiian" : 5},
        4 : {"Classic Cheese" : 5},
        5 : {"Classic Veggie" : 5},
        6 : {"Margherita" : 8.50},
        7 : {"Hot & Spicy Veggie" : 8.50},
        8 : {"Pepperoni" : 8.50},
        9 : {"Meat Lovers" : 8.50},
        10: {"Buffalo Chicken" : 8.50},
        }

Not exactly as slice, but you can do

>>> [next(iter(MENU[i])) for i in [1, 2, 3, 4]]
['Ham & Cheese', 'Cheesy Garlic', 'Hawaiian', 'Classic Cheese']

As you can see, from the above, it is possible, but it’s not exactly elegant.

So, I’d ask the question, why? Why do you have your data structured in that way, when there’s a much (IMHO) better way to do that.

Is it that you’ve been given that data structure, or is it that you don’t know how else to construct a ‘food menu’?

I’m not having a dig at you, btw: if you don’t know any different, there’s no shame in that, as you can learn, but if you do know how that could be done in a better way, than why have you done it like that?

1 Like

Just for fun: slice, chain, unpack and print on separate line

from itertools import islice, chain


stuff = {1 : {"Ham & Cheese" : 5},
         2 : {"Cheesy Garlic" : 5},
         3 : {"Hawaiian" : 5},
         4 : {"Classic Cheese" : 5},
         5 : {"Classic Veggie" : 5},
         6 : {"Margherita" : 8.50},
         7 : {"Hot & Spicy Veggie" : 8.50},
         8 : {"Pepperoni" : 8.50},
         9 : {"Meat Lovers" : 8.50},
         10: {"Buffalo Chicken" : 8.50},
         }

print(*chain.from_iterable(islice(stuff.values(),4)), sep="\n")

# prints
Ham & Cheese
Cheesy Garlic
Hawaiian
Classic Cheese

print(*chain.from_iterable(islice(stuff.values(),4, 6)), sep="\n")

# prints
Classic Veggie
Margherita
3 Likes

Honestly I only started coding a couple months ago, so I didn’t really know better. This was my first time ever needing to use a nested dictionary, and I didn’t realise that I had done it in an inefficient method.

That’s all fair enough.

As you can see, there’s a couple of solutions here and maybe you can follow the code, and maybe not.

Generally speaking, flat is better than nested. So, if you don’t need to nest, then it’s possibly better not to.

That said, there are times when nesting is a cleaner solution, but think about your data structure: "product", 2.99 , that’s a Tuple, right? That can be unpacked with item, price = ("product", 2.99) from which either or both can be displayed with the print() function.

You can can now have a dictionary of Tuples, which is less hassle to access; I’d make it function, like this:

def menu(key):
    items = {
        1: ("Ham & Cheese", 5),
        2: ("Cheesy Garlic", 5),
        3: ("Hawaiian", 5),
        4: ("Classic Cheese", 5)
        }
    return items.get(key)

… which can be accessed with name, price = menu(key) which in turn can be looped:

for key in range(1,5):
    name, price = menu(key)
    print(name, price)

Once you’re that far, and it’s doing what you want, you can get a little creative with the print() function within that loop and have something like this: print(f"{key}: {name.ljust(18,'.')}${price:0.2f}") which can look a little intimidating, but is not hard to pull apart, which would be a good thing for you to do, so that you expand on what you’ve already learned.

1 Like

That is a great advice from Rob. I thought of one more thing: Do you really need to explicitly define the item numbers? (The dictionary keys 1, 2, 3…)

If not, let a list make the indexes for you automatically just by the item position:

items = [
        ("Ham & Cheese", 5),
        ("Cheesy Garlic", 5),
        ("Hawaiian", 5),
        ("Classic Cheese", 5),
    ]

for item_index, (item_name, item_price) in enumerate(items, start=1):
    print(f'{item_index}: {item_name} {item_price}')
1: Ham & Cheese 5
2: Cheesy Garlic 5
3: Hawaiian 5
4: Classic Cheese 5
1 Like

Thank you. That was exactly where I was going with this, as the next point of learning, save for that fact that I would have retained the menu() function.

Does anyone know how to sum all the values, for all the items, in ‘total_price’.

My best attempt below, I got as far as getting the values but couldn’t sum them together.

It would be great if someone could tell me how to do it. (Code is condensed btw - part of a much larger, work in progress, program).

order_dictionary = {'Ham & Cheese': {'quantity': 2, 'price': 5, 'total_price': 10}, 'Hawaiian': {'quantity': 4, 'price': 5, 'total_price': 20}}

print("\n" + "*"*60 + "\nYour order:" + "\n")
for items in order_dictionary.items():
    idx, item = items
    print(f" {idx: <27} x{int(item['quantity']): <6}   ${item['total_price']:.2f}\n")
for food, info in order_dictionary.items():
    total = info['total_price']

This may help:

order_total = float() #set this up as a register

print("\n" + "*"*60 + "\nYour order:" + "\n")
for items in order_dictionary.items():
    idx, item = items
    print(f" {idx: <27} x{int(item['quantity']): <6}   ${item['total_price']:.2f}\n")
for food, info in order_dictionary.items():
    total = info['total_price']
    order_total += total  #this register now holds the total value of the order.

Remember to reset the order_total register to zero, if this routine it to be looped.