diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..5501c0088 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,4 +1,9 @@ // Predict and explain first... +// the code below has all the information for an address and is trying to log the house number to the console +// i expect it to log undefined or an error because the values in the object are not accessed correctly as its trying to use an index as if it is an array and not defined as a key in the object +// after running the code it came back as "my house number is `undefined`" +// i think using "address.houseNumber" or "address["houseNumber"] would work instead of "address[0]" + // This code should log out the houseNumber from the address object // but it isn't working... @@ -12,4 +17,5 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +// console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address["houseNumber"]}`); // corrected to print the house number from the address object diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..0975b7ba7 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,4 +1,10 @@ // Predict and explain first... +// i predict that the code is going to try to get the values from each of the keys in "author" and print them to the console +// i expect it to throw an error as its trying to loop for values of an array +// to fix this you would need to return an array from the values of author using "object.values()" so the "for...of" loops through each value in that array +// after running the code it gives a "TypeError: author is not iterable" +// this is because for...of only works on iterables like arrays, strings, maps, etc. but author is a plain object which is not iterable by default. + // 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 @@ -11,6 +17,6 @@ const author = { alive: true, }; -for (const value of author) { +for (const value of Object.values(author)){ console.log(value); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..b930ac142 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,8 +1,12 @@ // Predict and explain first... +// i expect the code to run but not produce the ingredients as its not calling the key pair values of ingredients array with the recipe.ingredients call +// i also expect that each part will not be produced on a new line when called as there is no new line breaks called with the \n after each property has been called in the console log // This program should log out the title, how many it serves and the ingredients. // Each ingredient should be logged on a new line // How can you fix it? +// to fix this you would need to change "${recipe}`" to "${recipe.ingredients}`" +// to fix each ingredient being called individually you'd use the array call on "recipe.ingredients[]\n" to call individual elements of the array and put them on a new line const recipe = { title: "bruschetta", @@ -10,6 +14,8 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +console.log( + `${recipe.title}\n serves ${ + recipe.serves + }\n ingredients:\n ${recipe.ingredients.join(", ")}` +); diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..6de748b2d 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,14 @@ -function contains() {} +function contains(obj, key) { + // check if "obj" is an object and not an array and we are working with plain objects + if (typeof obj !== "object" || obj === null || Array.isArray(obj)) + return false; + // loop over each property name in the object + for (let properties in obj) { + // check that if each of the properties names matches what were looking for in the key and return true if matches + if (properties === key) return true; + } + + return false; // if no object or key is found return false +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..92f827417 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,27 @@ as the object doesn't contains a key of 'c' // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); - +test("when given an 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("when given an object with existing properties returns true", () => { + expect(contains({a: 1, b: 2}, "a")).toBe(true); + expect(contains({a: 2, b: 4, c: 5}, "c")).toBe(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("when given an object with non existent properties returns false", () => { + expect(contains({a: 1, b: 2,}, "c")).toBe(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("when given an invalid parameters like arrays returns false", () => { + expect(contains([1, 2, 3], 1)).toBe(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..2484d831c 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,14 @@ -function createLookup() { +function createLookup(pairs) { // implementation here + const results = {}; // create an empty object to be able to store results + + // loop through each of the pairs in the array + for (const [country, currency] of pairs){ + // add new key value pairs to the object "country" is the key and "currency" is the value + results[country] = currency; + } + + return results; // returns the final object that maps each key to the corresponding values } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..cdd814f96 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,7 +1,13 @@ 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'], ['GB', 'GBP']])) + .toEqual({ US: 'USD', CA: 'CAD', GB: 'GBP' }); +}); + +test("returns an empty object when given an empty array", () => { + expect(createLookup([])).toEqual({}); +}); /* Create a lookup object of key value pairs from an array of code pairs diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..1cd70a63c 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,7 +6,12 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + // split only the first "=" to handle cases where the value contains "=" + const [key, ...rest] = pair.split("="); + + // rejoin the rest incase there are "=" in the value + const value = rest.join("="); + queryParams[key] = value; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..a99dad051 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -10,3 +10,15 @@ test("parses querystring values containing =", () => { "equation": "x=y+1", }); }); + +test("parses keys with multiple = signs in value", () => { + expect(parseQueryString("foo=bar=baz=qux")).toEqual({ + foo: "bar=baz=qux", + }); +}); + +test("parses querystring with no value", () => { + expect(parseQueryString("keyOnly")).toEqual({ + "keyOnly": "", + }); +}); \ No newline at end of file diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..86fe32d92 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,21 @@ -function tally() {} +function tally(array) { + // ensures that the input is an array. + if (!Array.isArray(array)) { + // throw an error if input is not an array + throw new Error("expected input to be an array"); + } + + // make an empty object to store items counted + const itemCount = Object.create(null); + + // loop over each item in the array + for (const item of array) { + // if the item hasn't been counted yet treat it as 0 + itemCount[item] = (itemCount[item] || 0) + 1; // then adds 1 to either start or increment the count for this item + } + + return itemCount; +} +console.log(tally(["toString", "toString"])); module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..658e9cb5a 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("counts duplicate items in an array", () => { + expect(tally(["a", "b", "a", "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("throws an error when an invalid input is given", () => { + expect(() => tally("not an array")).toThrow(Error); +}); \ No newline at end of file diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..3fb0ad23b 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,7 +6,7 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { +/* function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { @@ -15,15 +15,32 @@ function invert(obj) { return invertedObj; } +*/ // a) What is the current return value when invert is called with { a : 1 } +// answer: the current return value is {key : 1} because the key is not being set correctly // b) What is the current return value when invert is called with { a: 1, b: 2 } +// answer: the current return value is {key : 2} because the key is not being set correctly and it overwrites the previous key-value pair // c) What is the target return value when invert is called with {a : 1, b: 2} +// answer: the target return values should be {"1": "a", "2": "b"} because we want to swap the keys and values around in the object // c) What does Object.entries return? Why is it needed in this program? +// answer: Object.entries returns an array of key values pairs from the object to make it easier to iterate through object properties // d) Explain why the current return value is different from the target output +// answer: the current return value is different from the target output because the key is not being set correctly in the invertedObj instead of setting the value as the key it is setting the key as the value. // e) Fix the implementation of invert (and write tests to prove it's fixed!) +// answer: to fix this we have need to change the line "invertedObj.key = value;" to "invertedObj[value] = key;" so that the value is set as the key and the key is set to the value + +function invert(obj) { + const invertedObj = {}; + + for (const [key, value] of Object.entries(obj)) { + invertedObj[value] = key; + } + + return invertedObj; +} \ No newline at end of file