0

Hopefully a quick one but knowing me it won't be. I am writing a small App for myself, I collect Silver Coins, I will be doing more than silver in the future, but for now I would like to record what I have, the plan is to use Comboboxes to display only data that is required for each subsiquent Combobox

The data that each coin has are (Metal_Type, Country, Coin_Type, Year, Fineness) As per below, I have a Country list for each Metal_Type (Gold, Silver, Platinum, Pallidium), Each country has at LEAST 1 coin and not all countries do all Metal_Types, some counties have more. Counting it, there will be at LEAST 54 IF statements for the Combobox Events

Is there a more appropriate way of managing this data, Dictionaries maybe?

{"Australia1": {"Silver": "Red Kangaroo", "Koala", "Kookaburra"}}                                   
{"Australia2": {"Gold": "Gold Nugget", "Dragon Rectangular Coin"}}
{"Australia3": {"Platinum": "coin1", "coin2"}}

and so forth

from tkinter import *
from tkinter import ttk


def draw_main_window():
    metals = ['Palladium',
              'Platinum',
              'Gold',
              'Silver']

    gold_country = ["Austria",
                    "Canada",
                    "China",
                    "Iran",
                    "Isle of Man",
                    "Israel",
                    "Kazakhstan",
                    "Malaysia",
                    "Malta",
                    "Mexico",
                    "New Zealand",
                    "Poland",
                    "Russia",
                    "Somalia",
                    "South Africa",
                    "Ukraine",
                    "United Kingdom",
                    "United States"]

    silver_country = ["Armenia",
                      "Australia",
                      "Austria",
                      "Canada",
                      "China",
                      "Congo (Republic)",
                      "Cook Islands",
                      "Isle of Man",
                      "Mexico",
                      "New Zealand",
                      "Niue/Fiji",
                      "Russia",
                      "Rwanda",
                      "Serbia",
                      "Somalia",
                      "South Africa",
                      "South Korea",
                      "Ukraine",
                      "United Kingdom",
                      "United States"]

    palladium_list = ["Australia",
                      "Canada",
                      "China",
                      "Portugal",
                      "Russia",
                      "United States"]

    platinum_list = ["Australia",
                     "Austria",
                     "Canada",
                     "Isle of Man",
                     "United Kingdom",
                     "United States"]

    def metal_click(event):
        metal_value = cmb_metal.get()

        if metal_value == "Palladium":
            cmb_country['values'] = palladium_list

        if metal_value == "Platinum":
            cmb_country['values'] = platinum_list

        if metal_value == "Gold":
            cmb_country['values'] = gold_country

        if metal_value == "Silver":
            cmb_country['values'] = silver_country

    def country_click(event):
        current_value = cmb_country.get()

        if current_value == "Australia":
            cmb_type['values'] = "Emu"

        if current_value == "Canada":
            cmb_type['values'] = "Palladium Maple Leaf"

    root = Tk()
    root.geometry("640x480")
    root.title("Silver-Inventory")

    Label(root, text="Metal").grid(column=0, row=0)
    Label(root, text="Country").grid(column=0, row=1)
    Label(root, text="Coin Type").grid(column=0, row=2)
    Label(root, text="Year").grid(column=0, row=3)
    Label(root, text="Metal").grid(column=0, row=4)
    Label(root, text="Fineness").grid(column=0, row=5)

    cmb_metal = ttk.Combobox(root, values=metals)
    cmb_metal.grid(column=1, row=0)
    cmb_metal.bind("<<ComboboxSelected>>", metal_click)

    cmb_country = ttk.Combobox(root)
    cmb_country.grid(column=1, row=1)
    cmb_country.bind("<<ComboboxSelected>>", country_click)

    cmb_type = ttk.Combobox(root)
    cmb_type.grid(column=1, row=2)

    root.mainloop()


draw_main_window()
martineau
  • 119,623
  • 25
  • 170
  • 301
pr0xibus
  • 39
  • 1
  • 7

2 Answers2

0

You can often convert a long series of if statements into a simple dictionary lookup.

For example, instead of this:

metal_value = cmb_metal.get()
if metal_value == "Palladium":
    cmb_country['values'] = palladium_list

if metal_value == "Platinum":
    cmb_country['values'] = platinum_list

if metal_value == "Gold":
    cmb_country['values'] = gold_country

if metal_value == "Silver":
    cmb_country['values'] = silver_country

... you can use a dictionary to create a mapping between the metal value and the list:

mapping = {
    "Palladium": palladium_list,
    "Platinum": platinum_list,
    "Gold": gold_country,
    "Silver": silver_country,
}
metal_value = cmb_metal.get()
cmb_country['values'] = mapping[metal_value]
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I would let the 'values' be `lambda: cmb_country.config(values=palladium_list)` and then call the function, and this type of mapping is called dictionary dispatch – Delrius Euphoria Jul 09 '21 at 21:04
0

I think nested dictionaries would be the good way to do it. I've always liked @Aaron Hall's Vividict class shown in his answer to the question What is the best way to implement nested dictionaries? because it makes it so easy to construct them. The concept comes from Perl and is called autovivification.

Here's a demonstration of how it might be used to hold the kind of data you have:

from pprint import pprint

# Quick and dirty way to define a bunch of constant strings to make it
# unnecessary to quote them in the code every place they are used.
namespace = globals()
for name in ("Gold Silver Platinum "
             "Armenia Austria Australia Canada China Isle_of_Man "
             "Coin1 Coin2 Coin3 Coin4".split()):
    namespace[name] = name


class Vividict(dict):
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value


data = {(Gold, Austria): [Coin1, Coin2],
        (Gold, Canada): [Coin1, Coin2, Coin3],
        (Gold, China): [Coin1, Coin2],
        (Silver, Armenia): [Coin1, Coin2],
        (Silver, Australia): [Coin1, Coin2],
        (Platinum, Australia): [Coin1],
        (Platinum, Austria): [Coin1, Coin2, Coin3],
        (Platinum, Canada): [Coin1, Coin2, Coin3, Coin4],
        (Platinum, Isle_of_Man): [Coin1, Coin2]}

d = Vividict()
for (metal, country), coins in data.items():
    d[metal][country] = coins

pprint(d)

Here's the nested dictionary that's created:

{'Gold': {'Austria': ['Coin1', 'Coin2'],
          'Canada': ['Coin1', 'Coin2', 'Coin3'],
          'China': ['Coin1', 'Coin2']},
 'Platinum': {'Australia': ['Coin1'],
              'Austria': ['Coin1', 'Coin2', 'Coin3'],
              'Canada': ['Coin1', 'Coin2', 'Coin3', 'Coin4'],
              'Isle_of_Man': ['Coin1', 'Coin2']},
 'Silver': {'Armenia': ['Coin1', 'Coin2'], 'Australia': ['Coin1', 'Coin2']}}
martineau
  • 119,623
  • 25
  • 170
  • 301