1

Is it possible to use the tabulate function with a dictionary that is three levels deep? I took this dictionary from source and modified it a bit just to use as an idea.

MENU = {
    "espresso": 
        {
        "ingredients 1": 
            {
            "water": 50,
            "coffee": 18,
            },
        "ingredients 2": 
            {
            "water": 55,
            "coffee": 20,
            }
        }
    },
    "latte": 
        {
        "ingredients 1": 
            {
            "water": 200,
            "coffee": 24,
            },
        "ingredients 2": 
            {
            "water": 225,
            "coffee": 30,
            }
        }
    },
    "cappuccino": 
        {
        "ingredients 1": 
            {
            "water": 150,
            "coffee": 45,
            },
        "ingredients 2": 
            {
            "water": 155,
            "coffee": 40,
            }
        }
    }
}

What I'm looking for table-wise is something like this:

  Drink        Info        Water  Coffee
--------      ------       -----  ------
Espresso    Ingredients 1    50     18
Espresso    Ingredients 2    55     20
Latte       Ingredients 1    50     18
Latte       Ingredients 2    55     20
Cappuccino  Ingredients 1    50     18
Cappuccino  Ingredients 2    55     20

or this:

  Drink        Info        Water  Coffee
--------      ------       -----  ------
Espresso    Ingredients 1    50     18
            Ingredients 2    55     20
Latte       Ingredients 1    50     18
            Ingredients 2    55     20
Cappuccino  Ingredients 1    50     18
            Ingredients 2    55     20
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
sabuu26
  • 11
  • 1

1 Answers1

0

Try:

MENU = {
    "espresso": {
        "ingredients 1": {
            "water": 50,
            "coffee": 18,
        },
        "ingredients 2": {
            "water": 55,
            "coffee": 20,
        },
    },
    "latte": {
        "ingredients 1": {
            "water": 200,
            "coffee": 24,
        },
        "ingredients 2": {
            "water": 225,
            "coffee": 30,
        },
    },
    "cappuccino": {
        "ingredients 1": {
            "water": 150,
            "coffee": 45,
        },
        "ingredients 2": {
            "water": 155,
            "coffee": 40,
        },
    },
}

fmt = "{:<20} {:<20} {:<20} {:<20}"

tmp = {}
for k1, v1 in MENU.items():
    for k2, v2 in v1.items():
        for k3, v3 in v2.items():
            tmp.setdefault((k1, k2), {})[k3] = v3

for (k1, k2), v in tmp.items():
    print(fmt.format(k1, k2, v["water"], v["coffee"]))

Prints:

Drink                Info                 Water                Coffee              
----------------------------------------------------------------------
espresso             ingredients 1        50                   18                  
espresso             ingredients 2        55                   20                  
latte                ingredients 1        200                  24                  
latte                ingredients 2        225                  30                  
cappuccino           ingredients 1        150                  45                  
cappuccino           ingredients 2        155                  40                            
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • You have coffee under the water column though – sabuu26 Sep 20 '22 at 20:31
  • @sabuu26 Fixed. – Andrej Kesely Sep 20 '22 at 20:35
  • Amazing! Can you explain the fmt portion? If you had more than just water and coffee, would you just add more in the fmt? – sabuu26 Sep 20 '22 at 20:44
  • @sabuu26 `str.format` uses it's [own syntax](https://docs.python.org/3/library/string.html#format-string-syntax). `{:<20}` means 20-char fixed with aligned to the left. Of course, you can add more to the `fmt` string - even construct it programmatically – Andrej Kesely Sep 20 '22 at 20:46
  • @sabuu26 One note: if you plan to do tabular operations against numerical data, I recommend to look at `pandas` module. – Andrej Kesely Sep 20 '22 at 20:48
  • Thanks for the advice! Will have to look into it. One other thing I noticed is that, each item is now a part of one string, and its not just several strings within a list. So it's actually like this: ['espresso ingredients 1 50 18'] when I want this: mylist = ["espresso", "ingredients 1", "50", "18"] This is what I see after this line "print(fmt.format(k1, k2, v["water"], v["coffee"]))" each time – sabuu26 Sep 20 '22 at 22:47