Key of Max Value

PythonPythonBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In Python, dictionaries are a useful data structure that allows you to store key-value pairs. Sometimes, you may need to find the key of the maximum value in a dictionary. In this challenge, you will write a function that takes a dictionary as an argument and returns the key of the maximum value in the dictionary.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ModulesandPackagesGroup(["Modules and Packages"]) python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python(("Python")) -.-> python/DataStructuresGroup(["Data Structures"]) python/BasicConceptsGroup -.-> python/comments("Comments") python/ControlFlowGroup -.-> python/conditional_statements("Conditional Statements") python/DataStructuresGroup -.-> python/tuples("Tuples") python/DataStructuresGroup -.-> python/dictionaries("Dictionaries") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/build_in_functions("Build-in Functions") python/ModulesandPackagesGroup -.-> python/importing_modules("Importing Modules") python/ModulesandPackagesGroup -.-> python/standard_libraries("Common Standard Libraries") subgraph Lab Skills python/comments -.-> lab-13677{{"Key of Max Value"}} python/conditional_statements -.-> lab-13677{{"Key of Max Value"}} python/tuples -.-> lab-13677{{"Key of Max Value"}} python/dictionaries -.-> lab-13677{{"Key of Max Value"}} python/function_definition -.-> lab-13677{{"Key of Max Value"}} python/build_in_functions -.-> lab-13677{{"Key of Max Value"}} python/importing_modules -.-> lab-13677{{"Key of Max Value"}} python/standard_libraries -.-> lab-13677{{"Key of Max Value"}} end

Creating the Basic Function

Let's start by creating the core of our function. We'll build it up step-by-step. First, create a file named key_of_max.py. You can use the built-in LabEx code editor, or a terminal-based editor like nano or vim. Inside key_of_max.py, add the following code:

Code editor with key_of_max function
def key_of_max(d):
  """
  Returns the key associated with the maximum value in the dictionary 'd'.

  If multiple keys share the maximum value, any one of them may be returned.
  """
  return max(d, key=d.get)

Here's a breakdown:

  • def key_of_max(d):: This defines a function named key_of_max. It takes one argument, d, which represents the dictionary we'll be working with.
  • return max(d, key=d.get): This is the heart of the function. Let's analyze it piece by piece:
    • max(d, ...): The built-in max() function finds the largest item. By default, if you give max() a dictionary, it will find the largest key (alphabetically). We don't want that; we want the key associated with the largest value.
    • key=d.get: This is the crucial part. The key argument tells max() how to compare items. d.get is a method of dictionaries. When you call d.get(some_key), it returns the value associated with some_key. By setting key=d.get, we're telling max(): "Compare the items in the dictionary d by using their values, not their keys." The max() function then returns the key corresponding to that maximum value.

Handling the Empty Dictionary Case

Our current function has a problem: it will crash if the input dictionary d is empty. Let's fix that. Modify key_of_max.py to look like this:

def key_of_max(d):
  """
  Returns the key associated with the maximum value in the dictionary 'd'.

  If multiple keys share the maximum value, any one of them may be returned.
  """
  if not d:  ## Check if the dictionary is empty
      return None
  return max(d, key=d.get)

The added lines do the following:

  • if not d:: In Python, an empty dictionary is considered "falsy." This if statement checks if the dictionary d is empty.
  • return None: If the dictionary is empty, there's no maximum value, so we return None. This is a standard way to indicate the absence of a value in Python. This prevents the max() function from raising an error.

This is a crucial step in writing robust code: always consider edge cases!

Creating Unit Tests: Basic Tests

Now, let's write some tests to make sure our function works correctly. We'll use Python's unittest module. Create a new file named test_key_of_max.py and add the following code:

import unittest
from key_of_max import key_of_max  ## Import our function

class TestKeyOfMax(unittest.TestCase):

    def test_basic_case(self):
        self.assertEqual(key_of_max({'a': 4, 'b': 0, 'c': 13}), 'c')

    def test_another_case(self):
        self.assertEqual(key_of_max({'apple': 10, 'banana': 5, 'orange': 10}), 'apple')

if __name__ == '__main__':
    unittest.main()

Explanation:

  1. import unittest: Imports the testing framework.
  2. from key_of_max import key_of_max: Imports the function we want to test.
  3. class TestKeyOfMax(unittest.TestCase):: Defines a test class. Test classes group related tests together.
  4. def test_basic_case(self):: Defines a test method. Each test method checks a specific aspect of our function. Test method names must start with test_.
  5. self.assertEqual(...): This is an assertion. It checks if two values are equal. If they are not equal, the test fails. In this case, we're checking if key_of_max({'a': 4, 'b': 0, 'c': 13}) returns 'c', which it should.
  6. def test_another_case(self):: Added another test case to verify the key of the max value which may not be unique.
  7. if __name__ == '__main__': unittest.main(): This standard Python idiom runs the tests when you execute the script directly (e.g., python3 test_key_of_max.py).

Run the tests from your terminal: python3 test_key_of_max.py. You should see output indicating that the two tests passed.

python3 test_key_of_max.py
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

Testing the Empty Dictionary (Edge Case)

Let's add a test specifically for the empty dictionary case. Add this method to your TestKeyOfMax class in test_key_of_max.py:

    def test_empty_dictionary(self):
        self.assertIsNone(key_of_max({}))
  • self.assertIsNone(...): This assertion checks if the value is specifically None. This is important because self.assertEqual(..., None) could pass for things that evaluate to None, but aren't actually None. assertIsNone is more strict.

Run the tests again (python3 test_key_of_max.py). All three tests (the two basic tests and the empty dictionary test) should now pass.

python3 test_key_of_max.py
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Testing with All Negative Values

As a final test, let's handle a case where all the values in the dictionary are negative. Add this method to TestKeyOfMax:

    def test_all_negative_values(self):
        self.assertEqual(key_of_max({'x': -5, 'y': -2, 'z': -10}), 'y')

This test ensures that our function correctly identifies the least negative value (which is the maximum in this case) and returns its associated key.

Run your tests one last time (python3 test_key_of_max.py). All four tests should pass. This gives us high confidence that our function is working correctly.

Your complete test_key_of_max.py should now look like this:

import unittest
from key_of_max import key_of_max

class TestKeyOfMax(unittest.TestCase):

    def test_basic_case(self):
        self.assertEqual(key_of_max({'a': 4, 'b': 0, 'c': 13}), 'c')

    def test_another_case(self):
        self.assertEqual(key_of_max({'apple': 10, 'banana': 5, 'orange': 10}), 'apple')

    def test_empty_dictionary(self):
        self.assertIsNone(key_of_max({}))

    def test_all_negative_values(self):
        self.assertEqual(key_of_max({'x': -5, 'y': -2, 'z': -10}), 'y')

if __name__ == '__main__':
    unittest.main()

Run the tests again (python3 test_key_of_max.py). All four tests should pass. This gives us high confidence that our function is working correctly.

python3 test_key_of_max.py
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

Summary

In this lab, you built a Python function, key_of_max, to find the key associated with the largest value in a dictionary. You learned how to use the max() function with a custom key argument, and you handled the important edge case of an empty dictionary. You also wrote thorough unit tests using the unittest module, covering basic cases, empty dictionaries, and dictionaries with all negative values. This combination of functional code and comprehensive testing demonstrates good software development practices.