Skip to content

Commit 0960929

Browse files
implemented the key, value conversion and written jest tests all passed
1 parent 5ebaa3d commit 0960929

2 files changed

Lines changed: 98 additions & 12 deletions

File tree

‎Sprint-2/interpret/invert.js‎

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,50 @@
77
// E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"}
88

99
function invert(obj) {
10-
const invertedObj = {};
11-
12-
for (const [key, value] of Object.entries(obj)) {
13-
invertedObj.key = value;
10+
// Validate input type
11+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
12+
throw new Error("Input must be an object");
1413
}
1514

16-
return invertedObj;
17-
}
15+
const entries = Object.entries(obj);
16+
if (entries.length === 0) return {};
1817

19-
// a) What is the current return value when invert is called with { a : 1 }
18+
// take only the values
19+
const values = entries.map(([_, v]) => v);
2020

21-
// b) What is the current return value when invert is called with { a: 1, b: 2 }
21+
// Detect duplicate values
22+
const hasDuplicate = new Set(values).size !== values.length;
23+
if (hasDuplicate) {
24+
throw new Error("Values cannot be duplicated");
25+
}
2226

23-
// c) What is the target return value when invert is called with {a : 1, b: 2}
27+
const inverted = {};
2428

25-
// c) What does Object.entries return? Why is it needed in this program?
29+
for (const [key, value] of entries) {
30+
// Validate key and value types
31+
if (
32+
(typeof key !== "string" && typeof key !== "number") ||
33+
(typeof value !== "string" && typeof value !== "number")
34+
) {
35+
throw new Error("Keys and values must be a string or a number");
36+
}
2637

27-
// d) Explain why the current return value is different from the target output
38+
inverted[value] = key;
39+
}
40+
41+
return inverted;
42+
}
43+
module.exports = invert;
2844

29-
// e) Fix the implementation of invert (and write tests to prove it's fixed!)
45+
// a) What is the current return value when invert is called with { a : 1 }
46+
// the current value is 1
47+
// b) What is the current return value when invert is called with { a: 1, b: 2 }
48+
// the current return value at this call is 2
49+
// c) What is the target return value when invert is called with {a : 1, b: 2}
50+
// the target return value at this call is to supposed to be 'b'
51+
// d) What does Object.entries return? Why is it needed in this program?
52+
// Object.entries is used because both key and value are needed to be returned from the loop
53+
// e) Explain why the current return value is different from the target output
54+
// it's because the code in the line 13 is only returning single literal property named "key" on every loop iteration, so each assignment overwrites the previous one and the final object ends up with { key: 2 } but the intended inverted output requires using the loop variables as property names (dynamic keys) so each iteration creates a distinct property (for example invertedObj[value] = key), producing separate entries like { 1: 'a', 2: 'b' } instead of repeatedly writing to the same "key" property which the current function is doing
55+
// f) Fix the implementation of invert (and write tests to prove it's fixed!)
56+
// Above is the fixed function

‎Sprint-2/interpret/invert.test.js‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const invert = require("./invert");
2+
3+
test("inverts a simple object", () => {
4+
const input = { a: "x", b: "y" };
5+
const expected = { x: "a", y: "b" };
6+
expect(invert(input)).toEqual(expected);
7+
});
8+
9+
test("inverts an object with number values", () => {
10+
const input = { a: 1, b: 2 };
11+
const expected = { 1: "a", 2: "b" };
12+
expect(invert(input)).toEqual(expected);
13+
});
14+
15+
test("accepts empty string as a key", () => {
16+
const input = { "": "x" };
17+
const expected = { x: "" };
18+
expect(invert(input)).toEqual(expected);
19+
});
20+
21+
test("returns an empty object when input is empty", () => {
22+
expect(invert({})).toEqual({});
23+
});
24+
25+
test("throws when input is null", () => {
26+
expect(() => invert(null)).toThrow("Input must be an object");
27+
});
28+
29+
test("throws when input is not an object", () => {
30+
expect(() => invert("hello")).toThrow("Input must be an object");
31+
expect(() => invert(123)).toThrow("Input must be an object");
32+
expect(() => invert(true)).toThrow("Input must be an object");
33+
});
34+
35+
test("throws when input is an array", () => {
36+
expect(() => invert(["a", "b"])).toThrow("Input must be an object");
37+
});
38+
39+
test("throws when a value is not a string or number", () => {
40+
const obj = { a: {} };
41+
expect(() => invert(obj)).toThrow(
42+
"Keys and values must be a string or a number"
43+
);
44+
});
45+
46+
test("throws when values are duplicated (string)", () => {
47+
const obj = { a: "x", b: "y", c: "x" };
48+
expect(() => invert(obj)).toThrow("Values cannot be duplicated");
49+
});
50+
51+
test("throws when numeric values are duplicated", () => {
52+
const obj = { a: 1, b: 2, c: 1 };
53+
expect(() => invert(obj)).toThrow("Values cannot be duplicated");
54+
});
55+
56+
test("duplicate keys are overwritten by JavaScript before reaching invert()", () => {
57+
const obj = { a: "x", a: "y" }; // JS overwrites first 'a'
58+
expect(invert(obj)).toEqual({ y: "a" });
59+
});

0 commit comments

Comments
 (0)