diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..1b79994c6 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,4 +1,6 @@ // Predict and explain first... +// it will print : My house number is undefined +//objects aren't indexed // This code should log out the houseNumber from the address object // but it isn't working... @@ -12,4 +14,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..27c25c3a6 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,4 +1,6 @@ // Predict and explain first... +//for...of works only on iterable data types +// we will get an error // 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 +13,6 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); +for (const key in author) { + console.log(author[key]); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..b0244844f 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,4 +1,8 @@ // Predict and explain first... +//this will log: bruschetta serves 2 ingredients: title: "bruschetta", + // serves: 2, + // ingredients: ["olive oil", "tomatoes", "salt", "pepper"], +//instead of the ingredients it prints the whole object again , also there is no \n // This program should log out the title, how many it serves and the ingredients. // Each ingredient should be logged on a new line @@ -10,6 +14,10 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +let ingredients=[] + for(let ingredient of recipe.ingredients){ + ingredients.push(ingredient) + } + console.log( + `${recipe.title} serves ${recipe.serves} ingredients:\n${ingredients.join("\n")}`) + diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..58f57414e 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,18 @@ -function contains() {} +function contains(obj, propertyName) { + if ( + typeof obj !== "object" || + obj === null || + Array.isArray(obj) || + Object.keys(obj).length === 0 + ) { + throw new Error("Invalid object"); + } + + if (Object.keys(obj).includes(propertyName)) { + return true; + } + return false; +} + module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..699a3fccf 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,32 @@ 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("contains on empty object and propertyName='k' returns false", () => { + expect(()=>contains({}, "k")).toThrow("Invalid object"); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test( + "when contains is called with an object and an existing property name as arguments,it returns true ",()=>{ + expect(contains({a:9},"a")).toEqual(true) + } +); + // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("when contains is called with an object and a non-existing property name as arguments,it returns false ", () => { + expect(contains({ a: 9,color:"pink",day:"Sunday" }, "John")).toEqual(false); +}); + // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("when contains is called with the string 'parameter' and propertyName='a' as arguments it throws an error", () => { + expect(() => contains("parameter", "a")).toThrow("Invalid object"); +}); + diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..ad2e95bda 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,19 @@ -function createLookup() { - // implementation here +function createLookup(array) { + let object={} + for(let element of array){ + let key=element[0] + let value=element[1] + object[key]=value + } + return object } +console.log( + createLookup([ + ["US", "USD"], + ["CA", "CAD"], + ]) +); + + module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..9c37d1d6c 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,16 @@ 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,when createLookup is passed[['US', 'USD'], ['CA', 'CAD']] it returns {'US': 'USD','CA': 'CAD'}", () => { + 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..8eec34cc0 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,11 +6,18 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + const indexOfEqual = pair.indexOf("="); + if (indexOfEqual === -1) { + queryParams[pair] = ""; + } else { + const key = [pair.slice(0, indexOfEqual)]; + const value = pair.slice(indexOfEqual + 1); + queryParams[key] = value; + } } return queryParams; } +console.log(parseQueryString("=equationtu")); module.exports = parseQueryString; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..c127aecce 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,25 @@ // Below is one test case for an edge case the implementation doesn't handle well. // Fix the implementation for this test, and try to think of as many other edge cases as possible - write tests and fix those too. -const parseQueryString = require("./querystring.js") +const parseQueryString = require("./querystring.js"); test("parses querystring values containing =", () => { expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", + equation: "x=y+1", }); }); + +test("parses multiple querystring divided by &", () => { + expect(parseQueryString("equation=x=y+1&color=blue")).toEqual({ + equation: "x=y+1", + color: "blue", + }); +}); + +test("it returns the value as an empty string if the querystring has no =", () => { + expect(parseQueryString("day")).toEqual({ day: "" }); +}); + +test("it returns the key as an empty string if the querystring has no nothing before =", () => { + expect(parseQueryString("=day")).toEqual({ "": "day" }); +}); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..d169c1f7e 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,12 @@ -function tally() {} +function tally(array) { + if (!Array.isArray(array)) { + throw new Error("Invalid input"); + } + let obj = {}; + array.forEach((elem) => { + obj[elem] = (obj[elem] || 0) + 1; + }); + return obj; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..c4a934900 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("when an empty array is passed to tally it 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("when an array with duplicate items is passed to tally , it returns counts for each unique item", () => { + expect(tally(["t", "d", 5, "t", 5])).toEqual({ t: 2, d: 1, 5: 2 }); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error +test("when a string is passed to tally it throws error", () => { + expect(() => tally("asd")).toThrow("Invalid input"); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..25de7b376 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -7,23 +7,32 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} function invert(obj) { + if (typeof obj !== "object" || Array.isArray(obj) || obj === null) + throw new Error("Invalid input"); const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; } +module.exports = invert; + // a) What is the current return value when invert is called with { a : 1 } +//{key=1} // b) What is the current return value when invert is called with { a: 1, b: 2 } +//{key:2} // c) What is the target return value when invert is called with {a : 1, b: 2} +//{"1":"a","2":"b"} // c) What does Object.entries return? Why is it needed in this program? +//it returns the key:value pairs of obj,it's needed to extract those pairs from obj // d) Explain why the current return value is different from the target output +//because it's using invertedObj.key = value; instead of invertedObj[value] = key; // e) Fix the implementation of invert (and write tests to prove it's fixed!) diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..56c6aef71 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,20 @@ +const invert = require("./invert.js"); +test("when passed a string invert will throw error", () => { + expect(() => invert("asd")).toThrow("Invalid input"); +}); + +test("when passed an empty object, invert returns an empty object", () => { + expect(invert({})).toEqual({}); +}); + +test("when passed an object containing one key:value pair, invert returns an object containing value:key", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); +}); + +test("when passed an object containing multiple key:value pairs, invert returns an object containing value:key pairs", () => { + expect(invert({ a: 1, apple: "red", month: "September" })).toEqual({ + 1: "a", + red: "apple", + September: "month", + }); +}); diff --git a/Sprint-2/stretch/count-words.js b/Sprint-2/stretch/count-words.js index 8e85d19d7..6ab05ee67 100644 --- a/Sprint-2/stretch/count-words.js +++ b/Sprint-2/stretch/count-words.js @@ -26,3 +26,15 @@ 3. Order the results to find out which word is the most common in the input */ +function countWords(string) { + const noPunctuation = string.replace(/[.,!?]/g,""); + const array = noPunctuation.toLowerCase().split(" "); + + + let object = {}; + array.forEach((word) => { + object[word] = (object[word] || 0) + 1; + }); + return Object.values(object).sort((a,b)=>b-a)/////?????? stuck on how to order it +} +console.log(countWords("You, and .me? and you me me")); diff --git a/Sprint-2/stretch/mode.js b/Sprint-2/stretch/mode.js index 3f7609d79..d7f149f48 100644 --- a/Sprint-2/stretch/mode.js +++ b/Sprint-2/stretch/mode.js @@ -9,7 +9,12 @@ // into smaller functions using the stages above function calculateMode(list) { - // track frequency of each value + let freqs = elementFrequency(list); + + return maxFrequency(freqs); +} + +function elementFrequency(list) { let freqs = new Map(); for (let num of list) { @@ -19,8 +24,10 @@ function calculateMode(list) { freqs.set(num, (freqs.get(num) || 0) + 1); } + return freqs; +} - // Find the value with the highest frequency +function maxFrequency(freqs) { let maxFreq = 0; let mode; for (let [num, freq] of freqs) { @@ -29,8 +36,9 @@ function calculateMode(list) { maxFreq = freq; } } - return maxFreq === 0 ? NaN : mode; } + + module.exports = calculateMode; diff --git a/Sprint-2/stretch/mode.test.js b/Sprint-2/stretch/mode.test.js index ca33c28a3..1f2d72353 100644 --- a/Sprint-2/stretch/mode.test.js +++ b/Sprint-2/stretch/mode.test.js @@ -9,7 +9,7 @@ const calculateMode = require("./mode.js"); // Example: // Given [2,4,1,2,3,2,1] // When calculateMode is called on [2,4,1,2,3,2,1] -// Then it should return 2 */ +// Then it should return 2 */ describe("calculateMode()", () => { test("returns the most frequent number in an array", () => { diff --git a/Sprint-2/stretch/till.js b/Sprint-2/stretch/till.js index 6a08532e7..7f926ad82 100644 --- a/Sprint-2/stretch/till.js +++ b/Sprint-2/stretch/till.js @@ -8,7 +8,10 @@ function totalTill(till) { let total = 0; for (const [coin, quantity] of Object.entries(till)) { - total += coin * quantity; + const coinWithOutTrailingP = coin.slice(0, -1); + const numberCoin = +coinWithOutTrailingP; + + total += numberCoin * quantity; } return `£${total / 100}`; @@ -21,11 +24,29 @@ const till = { "20p": 10, }; const totalAmount = totalTill(till); +console.log(totalAmount); // a) What is the target output when totalTill is called with the till object +//£4.40 // b) Why do we need to use Object.entries inside the for...of loop in this function? +// to get the key value pairs // c) What does coin * quantity evaluate to inside the for...of loop? +//NaN // d) Write a test for this function to check it works and then fix the implementation of totalTill +// const till1 = { +// "1p": 10, +// "5p": 6, +// "50p": 4, +// "20p": 10, +// }; + +const currentOutput = totalTill(till); +const expectedOutput = "£4.4"; + +console.assert( + currentOutput === expectedOutput, + `Expected ${expectedOutput}, got ${currentOutput}` +);