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"}.
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
// 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
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.
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
// 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
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"].
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
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
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.
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
// 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
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.
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
// 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
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.
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
// 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
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}.
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
// 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
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]].
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
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
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.
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
// 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
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}.
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
// 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
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.