Worked Examples: Dictionaries#

These worked solutions correspond to the exercises on the Dictionaries page.

How to use this notebook:

  • Try each exercise yourself first before looking at the solution

  • The code cells show both the code and its output

  • Download this notebook if you want to run and experiment with the code yourself

  • Your solution might look different - that’s fine as long as it gives the correct answer!


Exercise: First-Row Transition Metals Dictionary#

Problem: Create a dictionary where the keys are the names of the first-row transition metals, and the values are integers representing the number of valence electrons. Test your dictionary by printing some of the values.

Background: The first-row transition metals (also called 3d transition metals) are:

  • Scandium (Sc) through Zinc (Zn)

  • These elements have electrons filling the 3d and 4s orbitals

  • The number of valence electrons affects their chemical properties

transition_metals = {
    'scandium': 3,
    'titanium': 4,
    'vanadium': 5,
    'chromium': 6,
    'manganese': 7,
    'iron': 8,
    'cobalt': 9,
    'nickel': 10,
    'copper': 11,
    'zinc': 12
}

print(transition_metals)
{'scandium': 3, 'titanium': 4, 'vanadium': 5, 'chromium': 6, 'manganese': 7, 'iron': 8, 'cobalt': 9, 'nickel': 10, 'copper': 11, 'zinc': 12}

Explanation:

The valence electrons for transition metals typically include:

  • The 4s electrons (usually 2)

  • The 3d electrons (varying from 1 to 10)

For example:

  • Scandium (Sc): [Ar] 3d1 4s2 → 3 valence electrons

  • Iron (Fe): [Ar] 3d6 4s2 → 8 valence electrons

  • Zinc (Zn): [Ar] 3d10 4s2 → 12 valence electrons

Note: There are some exceptions to the pattern (like chromium and copper) where electrons are rearranged for stability, but the total valence electron count shown here is correct.

Testing the Dictionary#

Let’s test our dictionary by printing some values:

# Access individual elements
print(f"Iron has {transition_metals['iron']} valence electrons")
print(f"Copper has {transition_metals['copper']} valence electrons")
print(f"Zinc has {transition_metals['zinc']} valence electrons")
Iron has 8 valence electrons
Copper has 11 valence electrons
Zinc has 12 valence electrons

We can also print all the key-value pairs:

for metal, electrons in transition_metals.items():
    print(f"{metal.capitalize()}: {electrons} valence electrons")
Scandium: 3 valence electrons
Titanium: 4 valence electrons
Vanadium: 5 valence electrons
Chromium: 6 valence electrons
Manganese: 7 valence electrons
Iron: 8 valence electrons
Cobalt: 9 valence electrons
Nickel: 10 valence electrons
Copper: 11 valence electrons
Zinc: 12 valence electrons

Additional Operations#

Check if a metal is in our dictionary:

print('iron' in transition_metals)
print('gold' in transition_metals)  # Gold is in the second row
True
False

Get the number of metals:

print(f"Number of first-row transition metals: {len(transition_metals)}")
Number of first-row transition metals: 10

Find metals with specific numbers of valence electrons:

Let’s find all metals that have 8 valence electrons. We’ll show two approaches.

Approach 1: Using a loop with an if statement

# Find metals with 8 valence electrons using a loop
metals_with_8_electrons = []

for metal, electrons in transition_metals.items():
    if electrons == 8:
        metals_with_8_electrons.append(metal)

print(f"Metals with 8 valence electrons: {metals_with_8_electrons}")
Metals with 8 valence electrons: ['iron']

Explanation:

  1. Create an empty list metals_with_8_electrons

  2. Loop through each metal and its electron count

  3. If the electron count equals 8, append the metal name to our list

  4. Print the result

Approach 2: Using a list comprehension

We can do the same thing more concisely using a list comprehension:

# Find metals with 8 valence electrons using a list comprehension
metals_with_8_electrons = [metal for metal, electrons in transition_metals.items() if electrons == 8]

print(f"Metals with 8 valence electrons: {metals_with_8_electrons}")
Metals with 8 valence electrons: ['iron']

Explanation:

This single line does exactly the same thing as the loop above! Let’s break it down:

[metal for metal, electrons in transition_metals.items() if electrons == 8]

Reading from left to right:

[...] - Create a new list metal - Add this metal name to the list (this is what we want to collect) for metal, electrons in transition_metals.items() - Loop through key, value pairs in the dictionary if electrons == 8 - Only include metals where this condition is true

General pattern:

[expression for item in iterable if condition]

Which should you use?

Loop version: More explicit, easier to debug, better for complex operations List comprehension: More concise, “Pythonic”, good for simple operations

Both are correct - use whichever is clearer to you!

Adding More Information#

Dictionaries can store more complex data. Let’s create a more detailed version where each value is itself a dictionary:

detailed_metals = {
    'iron': {
        'symbol': 'Fe',
        'atomic_number': 26,
        'valence_electrons': 8,
        'electron_configuration': '[Ar] 3d6 4s2'
    },
    'copper': {
        'symbol': 'Cu',
        'atomic_number': 29,
        'valence_electrons': 11,
        'electron_configuration': '[Ar] 3d10 4s1'
    },
    'zinc': {
        'symbol': 'Zn',
        'atomic_number': 30,
        'valence_electrons': 12,
        'electron_configuration': '[Ar] 3d10 4s2'
    }
}

# Access nested dictionary values
print(f"Iron's symbol: {detailed_metals['iron']['symbol']}")
print(f"Copper's atomic number: {detailed_metals['copper']['atomic_number']}")
print(f"Zinc's electron configuration: {detailed_metals['zinc']['electron_configuration']}")
Iron's symbol: Fe
Copper's atomic number: 29
Zinc's electron configuration: [Ar] 3d10 4s2

Summary#

1. Creating Dictionaries#

  • Define key-value pairs using {key: value} syntax

  • Keys should be descriptive (like element names)

  • Values can be any data type (here: integers)

2. Accessing Dictionary Values#

  • Use square brackets: dictionary[key]

  • Use .get(key) for safe access that won’t raise errors

3. Iterating Over Dictionaries#

  • .items() gives both keys and values

  • .keys() gives just keys

  • .values() gives just values

4. Nested Dictionaries#

  • Values can be dictionaries themselves

  • Access using multiple brackets: dict[key1][key2]

  • Useful, e.g., for storing multiple properties per element