diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..500678113 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -12,4 +12,7 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address["houseNumber"]}`); +// to access the houseNumber of the object using bracket notation, +// we need to use the key as a string. In this case, "houseNumber" +// is the correct key, so the code should work as expected. diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..88dee3e5a 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -3,13 +3,18 @@ // This program attempts to log out all the property values in the object. // But it isn't working. Explain why first and then fix the problem -const author = { - firstName: "Zadie", - lastName: "Smith", - occupation: "writer", - age: 40, - alive: true, -}; +// I think the issue with the original code is it was trying to loop over the object directly, +// which is not iterable. Instead, we should loop over the array that contains the object. + +const author = [ + { + firstName: "Zadie", + lastName: "Smith", + occupation: "writer", + age: 40, + alive: true, + }, +]; for (const value of author) { console.log(value); diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..36cade6d0 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -12,4 +12,5 @@ const recipe = { console.log(`${recipe.title} serves ${recipe.serves} ingredients: -${recipe}`); +${recipe.ingredients.join("\n")}`); //the DOT expression was missing in the original code. +// also adding a join method to the ingredients array to log each ingredient on a new line. diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..61ea51616 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,5 @@ -function contains() {} +function contains(obj, prop) { + return prop in obj; // checks if the property exists in the object and returns true or false +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..9701b0d8b 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -17,19 +17,31 @@ as the object doesn't contains a key of 'c' // When passed an object and a property name // Then it should return true if the object contains the property, false otherwise + // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); +test("contains on empty object returns false", () => { + expect(contains({}, "a")).toBe(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("contains an object returns true, or false otherwise", () => { + expect(contains({a: 1, b: 2, c: 3}, "a")).toBe(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("contains an object returns true, or false otherwise", () => { + expect(contains({a: 1, b: 2, c: 3}, "d")).toBe(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("contains an object returns true, or false otherwise", () => { + expect(contains([1, 2, 3, 'a'], "a")).toBe(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..95bd5e475 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,6 @@ -function createLookup() { - // implementation here +function createLookup(entries) { + let obj = Object.fromEntries(entries); + return obj; } -module.exports = createLookup; +module.exports = createLookup; \ No newline at end of file diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..65d5878e0 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,11 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); +test("creates a country currency code lookup for multiple codes", () => { + expect(createLookup([['US', 'USD'], ['CA', 'CAD']])).toEqual({ + 'US': 'USD', + 'CA': 'CAD' + }); +}); /* diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..ff2f0b4a5 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -3,11 +3,31 @@ function parseQueryString(queryString) { if (queryString.length === 0) { return queryParams; } + queryString = queryString.replace(/\+/g, " "); const keyValuePairs = queryString.split("&"); - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + if (pair === "") { + continue; + } + let key; + let value; + const index = pair.indexOf("="); + if (index === -1) { + key = decodeURIComponent(pair); + value = ""; + } else { + key = decodeURIComponent(pair.slice(0, index)); + value = decodeURIComponent(pair.slice(index + 1)); + } + if (!queryParams[key]) { + queryParams[key] = value; + } else { + if (Array.isArray(queryParams[key])) { + queryParams[key].push(value); + } else { + queryParams[key] = [queryParams[key], value]; + } + } } return queryParams; diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..961c8ebe9 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,20 @@ -function tally() {} +function tally(arr) { + let countOfItemsObj = {}; + if (!Array.isArray(arr)) { + throw new Error("Invalid input"); + } else if (arr.length < 1) { + return countOfItemsObj; + } else { + for (let element = 0; element < arr.length; element++) { + const exist = Object.hasOwn(countOfItemsObj, arr[element]); + if (!exist) { + countOfItemsObj[arr[element]] = 1; + } else { + countOfItemsObj[arr[element]] = countOfItemsObj[arr[element]] + 1; + } + } + } + return countOfItemsObj; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..5284747d9 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,12 +23,20 @@ const tally = require("./tally.js"); // Given an empty array // When passed to tally // Then it should return an empty object -test.todo("tally on an empty array returns an empty object"); +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("tally on an array with duplicate items returns counts for each unique item", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error +test("tally on an invalid input like a string throws an error", () => { + expect(() => tally("invalid input")).toThrow("Invalid input"); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..8cedb37da 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,20 +10,40 @@ function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } - return invertedObj; } // a) What is the current return value when invert is called with { a : 1 } +// the current return value is { key: 1 } // b) What is the current return value when invert is called with { a: 1, b: 2 } +// current return value is { key: 2 } // c) What is the target return value when invert is called with {a : 1, b: 2} +// the target return value is { "1": "a", "2": "b" } // c) What does Object.entries return? Why is it needed in this program? +// Object.entries returns an array of key-value pairs from the object. It is needed +// in this program to iterate over each key-value pair in the object so that we can +// swap them and create a new inverted object. // d) Explain why the current return value is different from the target output +// I think current return value is different from the return value because the +// current implementation is not really swapping the properties of the object. +// Instead, it is just creating a new property called "key" and assigning the +// value to it. The target output requires us to swap the keys and values, which +// is not happening in the current implementation. // e) Fix the implementation of invert (and write tests to prove it's fixed!) +console.assert( + JSON.stringify(invert({ a: 1 })) === JSON.stringify({ "1": "a" }), + "Test 1 failed" +); + +console.assert( + JSON.stringify(invert({ a: 1, b: 2 })) === + JSON.stringify({ "1": "a", "2": "b" }), + "Test 2 failed" +);