Rename Keys

A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
medium
Seniority
L3

Problem

Return a copy of record with every field listed in mapping renamed from its incoming name to its canonical one, so user records from different upstream systems line up, while fields the mapping does not list carry through unchanged. An entry in mapping for a field this record lacks has no effect.

Old names out. New names in.

Example 1

Input:

record = {"age":30,"eml":"alice@co.com","usr_nm":"alice"}, mapping = {"eml":"email","usr_nm":"username"}

Output:

{"age":30,"email":"alice@co.com","username":"alice"}

Example 2

Input:

record = {"a":1,"b":2}, mapping = {}

Output:

{"a":1,"b":2}

Worked solution and explanation

This is a key rename dressed up as record consolidation, and the whole question is which dict drives the work. Everyone gets the happy path. The candidates who slip loop over mapping and write record[new] = record.pop(old), quietly assuming every mapped field arrived. Hand that version a record from a system that never sent eml and it raises KeyError instead of returning the fields that did show up, and it mutates the caller's record on the way.

Let the record drive

Step 1: Visit the record's fields, not the mapping's

The output can only contain fields the record actually holds, so those are the keys worth walking. Mapping entries for fields that never arrived are then ignored for free: nothing has to check for them, and nothing can raise.

Step 2: Look each field up with itself as the fallback

mapping.get(key, key) settles both cases in one expression: a mapped field gets its canonical name, an unmapped one gets its own name back. No branch, no membership test, no special case for an empty mapping.

Step 3: Write into a fresh result

Building a new dict leaves the caller's record exactly as it came in, which matters when that raw record is also logged, retried, or compared upstream.

Record-driven rename with pass-through
def rename_keys(record, mapping):
    result = {}
    for key in record:
        new_key = mapping.get(key, key)
        result[new_key] = record[key]
    return result
Driven by the mapping
Iterating mapping.items() and moving record.pop(old) to new touches every mapping entry whether or not the field exists, so an empty record or one missing eml raises KeyError, and the input dict is rewritten in place.
Driven by the record
Iterating record touches only fields that exist. Absent mapping entries never come up, unmapped fields pass through via the fallback, and the input is never modified.

Common follow-up questions