Skip to content

← Everyday Standard Library Tools step 4 of 55

Easy Primitives

Group Rows by Key and Return a Plain dict

A report groups sales rows by region. Write group_by_key, which collects the values for each key into a list. Use a defaultdict while you build the groups, and hand back a plain dict. A caller who asks for a region that is not there must get a KeyError, not a new empty group.

group_by_key([("b", 1), ("a", 2), ("b", 3)])
# {"b": [1, 3], "a": [2]}

What to write

Fix group_by_key, and add type annotations to it and to solve:

def group_by_key(rows: list[tuple[str, int]]) -> dict[str, list[int]]: ...
def solve(
    rows: list[tuple[str, int]], probe: str
) -> tuple[list[tuple[str, list[int]]], str, str]: ...
  • Collect the values with defaultdict(list), then return a plain dict.
  • Keep the keys in the order they first appear. Do not sort them.
  • Keep each key's values in input order, including repeats, zero and negative numbers.
  • Give each key its own list, and leave the input rows unchanged.
  • Looking up a missing key in the returned dict must raise KeyError and must not add a group.
  • Your code must pass mypy --strict. Leave the logic of solve as it is.

Edge cases

  • Empty input returns an empty dict.
  • An empty string is a valid key.

What solve reports

The supplied solve(rows, probe) calls group_by_key, records the type name of the result, and then looks up grouped[probe]. It returns a tuple of three items:

  1. list(grouped.items()), taken after the lookup, as (key, values) tuples.
  2. type(grouped).__name__, which must be "dict".
  3. "KeyError" if the lookup raised KeyError, or "returned" if it found the key.

For rows [("b", 1), ("a", 2), ("b", 3)] and probe "missing", solve returns ([("b", [1, 3]), ("a", [2])], "dict", "KeyError"). With probe "a", the last item is "returned" and the other two stay the same.

The starter returns its defaultdict, so the type name is "defaultdict", and a missing probe adds an empty group to the items. The grader tells tuples from lists, so keep the tuples that solve builds.