Coding Practice / Module 7 · Objects / Problems 61–70

Module 7: Object & Dictionary Practice Problems

Everything Modules 1–3 did with strings, numbers and lists, now applied to key-value data: reversing, cloning, merging, converting between shapes, and grouping records by a shared field. JavaScript objects and Python dicts map onto each other almost one-to-one here — the syntax for reading and writing a key is really the only thing that changes.

Module 7 of 12 Problems 61–70 JS + Python ~45–60 Min

By the end of this module, you'll be able to

  • Tell a shallow clone from a deep clone, and know which one a given task needs
  • Convert between an object/dict and an array/list of [key, value] pairs in both directions
  • Bucket a list of records into groups keyed by one of their shared properties

1. Problems 61–70

Same format as the previous modules: expand a problem to see the approach and both commented solutions.

P61

Reverse Keys and Values of an Object

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

Approach: build a fresh object, walking the original's key-value pairs and writing each one back in with the value as the new key and the key as the new value.

JavaScript
reverse-key-values.js
// Build a new object where each original value becomes a key, and vice versa.
function reverseKeyValues(obj) {
  const reversed = {};
  for (const key in obj) {
    reversed[obj[key]] = key; // value becomes key, key becomes value
  }
  return reversed;
}

console.log(reverseKeyValues({ a: "1", b: "2", c: "3" }));
// { "1": "a", "2": "b", "3": "c" }
Python
reverse_key_values.py
def reverse_key_values(d: dict) -> dict:
    """Same idea: walk the dict's items and flip each pair."""
    reversed_d = {}
    for key, value in d.items():
        reversed_d[value] = key  # value becomes key, key becomes value
    return reversed_d

print(reverse_key_values({"a": "1", "b": "2", "c": "3"}))
# {'1': 'a', '2': 'b', '3': 'c'}
P62

Count Properties in an Object

{name, age, city} has 3 properties.

Approach: Object.keys() turns an object's own property names into an array, whose length is the count. Python's dict already reports its own length directly.

JavaScript
count-properties.js
// Object.keys() lists an object's own enumerable property names as an array.
function countProperties(obj) {
  return Object.keys(obj).length;
}

console.log(countProperties({ name: "Amit", age: 32, city: "Kolkata" })); // 3
Python
count_properties.py
def count_properties(d: dict) -> int:
    """A dict's length already counts its keys directly."""
    return len(d)

print(count_properties({"name": "Amit", "age": 32, "city": "Kolkata"}))  # 3
P63

Find Object Keys With a Particular Value

{a:1, b:2, c:1, d:1} where value is 1 → ["a", "c", "d"].

Approach: walk every key-value pair once, and collect the keys whose value matches the target.

JavaScript
keys-with-value.js
function keysWithValue(obj, target) {
  const matches = [];
  for (const key in obj) {
    if (obj[key] === target) matches.push(key);
  }
  return matches;
}

console.log(keysWithValue({ a: 1, b: 2, c: 1, d: 1 }, 1)); // ["a", "c", "d"]
Python
keys_with_value.py
def keys_with_value(d: dict, target) -> list:
    matches = []
    for key, value in d.items():
        if value == target:
            matches.append(key)
    return matches

print(keys_with_value({"a": 1, "b": 2, "c": 1, "d": 1}, 1))  # ['a', 'c', 'd']
P64

Remove a Property Without Mutating the Original

Drop key "b" from {a,b,c} and get a brand-new object back.

Approach: rather than deleting a key in place, build a new object/dict that includes every key except the one being removed — the original stays untouched.

JavaScript
remove-property.js
// Object destructuring can "pick everything except" a key: pull it out into its
// own variable, then spread whatever's left into a fresh object.
function removeProperty(obj, keyToRemove) {
  const { [keyToRemove]: removed, ...rest } = obj;
  return rest;
}

console.log(removeProperty({ a: 1, b: 2, c: 3 }, "b")); // { a: 1, c: 3 }
Python
remove_property.py
def remove_property(d: dict, key_to_remove: str) -> dict:
    """Build a new dict, excluding the target key -- the original is untouched."""
    return {key: value for key, value in d.items() if key != key_to_remove}

print(remove_property({"a": 1, "b": 2, "c": 3}, "b"))  # {'a': 1, 'c': 3}
P65

Shallow Clone an Object

Copy the top level so editing the clone leaves the original alone.

Approach: spreading (JS) or wrapping with dict() (Python) copies every top-level key into a brand-new container — but any nested object inside is still the same shared reference (see the next problem).

JavaScript
shallow-clone.js
// The spread operator copies each top-level property into a new object.
function shallowClone(obj) {
  return { ...obj };
}

const original = { a: 1, b: 2 };
const clone = shallowClone(original);
clone.a = 99;
console.log(original.a, clone.a); // 1 99 -- editing the clone didn't touch the original
Python
shallow_clone.py
def shallow_clone(d: dict) -> dict:
    """dict()/copy() both make a new top-level dict pointing at the same values."""
    return dict(d)

original = {"a": 1, "b": 2}
clone = shallow_clone(original)
clone["a"] = 99
print(original["a"], clone["a"])  # 1 99 -- editing the clone didn't touch the original
P66

Deep Clone a Nested Object

Editing a nested value in the clone must not touch the original.

Approach: recurse into every nested object/array and copy it too, instead of stopping at the top level. Both languages also ship this as a built-in (structuredClone() in JS, copy.deepcopy() in Python) — writing it manually once is what makes the built-in make sense.

JavaScript
deep-clone.js
// A shallow clone only copies the top level -- nested objects are still shared
// references. structuredClone() (or a recursive walk) copies every level.
function deepClone(obj) {
  if (obj === null || typeof obj !== "object") return obj; // primitives copy themselves
  const clone = Array.isArray(obj) ? [] : {};
  for (const key in obj) {
    clone[key] = deepClone(obj[key]); // recurse into nested objects/arrays
  }
  return clone;
}

const original = { a: 1, nested: { b: 2 } };
const clone = deepClone(original);
clone.nested.b = 99;
console.log(original.nested.b, clone.nested.b); // 2 99 -- the nested object is independent too
Python
deep_clone.py
import copy

def deep_clone(d):
    """Python's copy.deepcopy() recursively copies every nested level."""
    return copy.deepcopy(d)

original = {"a": 1, "nested": {"b": 2}}
clone = deep_clone(original)
clone["nested"]["b"] = 99
print(original["nested"]["b"], clone["nested"]["b"])  # 2 99
P67

Merge Two Objects

{a,b} + {b,c} → {a, b (from the second), c}.

Approach: spread both objects into one literal, second one last — whichever object's key comes later in the spread wins on a collision.

JavaScript
merge-objects.js
// Spreading two objects together merges them; keys from the second object
// overwrite matching keys from the first.
function mergeObjects(a, b) {
  return { ...a, ...b };
}

console.log(mergeObjects({ a: 1, b: 2 }, { b: 99, c: 3 })); // { a: 1, b: 99, c: 3 }
Python
merge_objects.py
def merge_objects(a: dict, b: dict) -> dict:
    """The ** unpacking operator does the same job in a dict literal."""
    return {**a, **b}

print(merge_objects({"a": 1, "b": 2}, {"b": 99, "c": 3}))  # {'a': 1, 'b': 99, 'c': 3}
P68

Convert an Object to an Array (and Back)

{a:1,b:2} ↔ [["a",1],["b",2]].

Approach: Object.entries()/.items() turns the object/dict into a list of [key, value] pairs; Object.fromEntries()/dict() builds it back from that same shape.

JavaScript
object-array-conversion.js
function objectToArray(obj) {
  return Object.entries(obj); // [["a", 1], ["b", 2]] -- an array of [key, value] pairs
}

function arrayToObject(entries) {
  return Object.fromEntries(entries); // the reverse: pairs back into an object
}

const pairs = objectToArray({ a: 1, b: 2 });
console.log(pairs); // [["a", 1], ["b", 2]]
console.log(arrayToObject(pairs)); // { a: 1, b: 2 }
Python
object_array_conversion.py
def object_to_array(d: dict) -> list:
    return list(d.items())  # [("a", 1), ("b", 2)] -- a list of (key, value) tuples

def array_to_object(pairs: list) -> dict:
    return dict(pairs)  # the reverse: pairs back into a dict

pairs = object_to_array({"a": 1, "b": 2})
print(pairs)  # [('a', 1), ('b', 2)]
print(array_to_object(pairs))  # {'a': 1, 'b': 2}
P69

Group an Array of Objects by a Property

Bucket a list of people by city.

Approach: for each item, look up its bucket by the grouping key; create that bucket the first time it's seen, then push the item into it. This is a very common real-world shape for turning a flat list into a report.

JavaScript
group-by.js
// A common real-world shape: bucket a list of records by one shared field.
function groupBy(items, key) {
  const groups = {};
  for (const item of items) {
    const groupKey = item[key];
    if (!groups[groupKey]) groups[groupKey] = []; // first item in this bucket
    groups[groupKey].push(item);
  }
  return groups;
}

const people = [
  { name: "Amit", city: "Kolkata" },
  { name: "Riya", city: "Delhi" },
  { name: "Sam", city: "Kolkata" },
];
console.log(groupBy(people, "city"));
// { Kolkata: [{name:"Amit",...}, {name:"Sam",...}], Delhi: [{name:"Riya",...}] }
Python
group_by.py
def group_by(items: list, key: str) -> dict:
    groups = {}
    for item in items:
        group_key = item[key]
        if group_key not in groups:
            groups[group_key] = []  # first item in this bucket
        groups[group_key].append(item)
    return groups

people = [
    {"name": "Amit", "city": "Kolkata"},
    {"name": "Riya", "city": "Delhi"},
    {"name": "Sam", "city": "Kolkata"},
]
print(group_by(people, "city"))
# {'Kolkata': [{'name': 'Amit', ...}, {'name': 'Sam', ...}], 'Delhi': [{'name': 'Riya', ...}]}
P70

Sort an Object's Entries by Value

{b:3, a:1, c:2} → {a:1, c:2, b:3}.

Approach: objects/dicts themselves can't be sorted directly — convert to an array of pairs first (problem 68's trick), sort that array by the value half of each pair, then convert it back.

JavaScript
sort-object-by-value.js
// Object.entries() turns it into an array (which CAN be sorted), then
// Object.fromEntries() turns the sorted array back into an object.
function sortObjectByValue(obj) {
  const entries = Object.entries(obj);
  entries.sort((a, b) => a[1] - b[1]); // compare the value half of each [key, value] pair
  return Object.fromEntries(entries);
}

console.log(sortObjectByValue({ b: 3, a: 1, c: 2 })); // { a: 1, c: 2, b: 3 }
Python
sort_object_by_value.py
def sort_object_by_value(d: dict) -> dict:
    """sorted() on .items(), keyed by the value half of each pair, then rebuild the dict."""
    sorted_items = sorted(d.items(), key=lambda pair: pair[1])
    return dict(sorted_items)

print(sort_object_by_value({"b": 3, "a": 1, "c": 2}))  # {'a': 1, 'c': 2, 'b': 3}

2. Key Takeaways

  • A shallow clone copies only the top level — any nested object inside is still a shared reference. Reach for a deep clone (or copy.deepcopy/structuredClone) whenever nested data needs to be independent too.
  • Converting an object/dict to an array of pairs is the bridge that lets you sort, filter or otherwise use array methods on data that doesn't natively support them.
  • "Group by" is really just a frequency map (Module 1) that collects matching items into a list instead of just incrementing a count.