diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..fde180d6d 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -12,4 +12,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..1c8cf3679 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -2,6 +2,12 @@ // 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 +/* +When I run the code I got this error (TypeError: author is not iterable). +Means that we can not do iteration through the author abject. +That's because plain objects aren't iterable like arrays. +To fix it, we need to convert the object into an iterable structure. +*/ const author = { firstName: "Zadie", @@ -11,6 +17,7 @@ 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..a413b3332 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -12,4 +12,4 @@ const recipe = { console.log(`${recipe.title} serves ${recipe.serves} ingredients: -${recipe}`); +${recipe.ingredients.join("\n")}`); diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..cd0b0a5e9 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,12 @@ -function contains() {} +function contains(object, keyName) { + if (Object.keys(object) == 0 || !Object.keys(object).includes(keyName) || typeof object !== "object") { + return false + } + else if (Object.keys(object).includes(keyName)) { + return true + } +}; + + module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..4427c99c0 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,45 @@ 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("It will return false when we call contains with an empty object", () => { + const input = {}; + const currentOutput = contains(input, "anyKey"); + const targetOutput = false; + expect(currentOutput).toStrictEqual(targetOutput); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("It will return true when we call contains with an existing property name", () => { + const input = { + name: "Ali", + age: 25, + }; + const currentOutput = contains(input, "name"); + const targetOutput = true; + expect(currentOutput).toStrictEqual(targetOutput); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("It will return false when we call contains with a non-existent property name", () => { + const input = { + name: "Ali", + age: 25, + }; + const currentOutput = contains(input, "city"); + const targetOutput = false; + expect(currentOutput).toStrictEqual(targetOutput); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("It will return false when we call contains with an array", () => { + const input = [] + const currentOutput = contains(input, "length"); + const targetOutput = false; + expect(currentOutput).toStrictEqual(targetOutput); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..8f926885a 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,15 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + if (countryCurrencyPairs.length == 0){ + return "array is empty" + } + console.log(countryCurrencyPairs.length) + let countryCurrencyObject = {} + for (const array of countryCurrencyPairs){ + countryCurrencyObject[array[0]] = array[1]; + } + return countryCurrencyObject; } +console.log(createLookup([])); + module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..d5ea986d0 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -33,3 +33,27 @@ It should return: 'CA': 'CAD' } */ + +test("throws error when createLookup is given an empty array", () => { + const input = []; + const currentOutput = createLookup(input); + const targetOutput = "array is empty"; + expect(currentOutput).toStrictEqual(targetOutput) + +}) + +test("handel the case when createLookup has only one array inside an array", () => { + const input = [['US', 'USD']]; + const currentOutput = createLookup(input); + const targetOutput = {'US': 'USD'}; + expect(currentOutput).toStrictEqual(targetOutput) + +}) + +test("handel the case when createLookup has more than one array inside an array", () => { + const input = [['US', 'USD'], ['CA', 'CAD']]; + const currentOutput = createLookup(input); + const targetOutput = {'US': 'USD', 'CA': 'CAD'}; + expect(currentOutput).toStrictEqual(targetOutput) + +}) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..68e35874f 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,11 +6,17 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + if (pair === "") { + continue; + } + const parts = pair.split("="); + const key = parts[0]; + const value = parts.slice(1).join("=") queryParams[key] = value; } return queryParams; } +console.log(parseQueryString("&&name=Ali&&")) module.exports = parseQueryString; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..566486cc5 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -10,3 +10,23 @@ test("parses querystring values containing =", () => { "equation": "x=y+1", }); }); + +test("handles empty value", () => { + expect(parseQueryString("username=")).toEqual({ username: "" }); +}); + +test("handles empty key", () => { + expect(parseQueryString("=value")).toEqual({ "": "value" }); +}); + +test("handles only ampersands", () => { + expect(parseQueryString("&&&&")).toEqual({}); +}); + +test("handles repeated keys", () => { + expect(parseQueryString("key=value1&key=value2")).toEqual({ key: "value2" }); +}); + +test("handles ampersands at start and end", () => { + expect(parseQueryString("&&name=Ali&&")).toEqual({ name: "Ali" }); +}); \ No newline at end of file diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..7bdfc122e 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,16 @@ -function tally() {} +function tally(arrayElements) { + const tallyObject = {} + for (const item of arrayElements) { + if (tallyObject[item]) { + tallyObject[item] += 1; + } + else { + tallyObject[item] = 1; + } + } + return tallyObject; +} +console.log(tally(['a', 'a', 'b', 'a'])) module.exports = tally; + diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..a5ab6904d 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,11 +23,33 @@ 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", () => { + const input = [] + const currentOutput = tally(input) + const targetOutput = {} + expect(currentOutput).toEqual(targetOutput) +}); + +// Given an array with one item +// When passed to tally +// Then it should return counts of the item, which is 1 +test("tally on an array with one item should return counts of the item, which is 1", () => { + const input = ['a', 'a'] + const currentOutput = tally(input) + const targetOutput = { a : 2} + expect(currentOutput).toEqual(targetOutput) +}); + // 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 should return counts for each unique item", () => { + const input = ['a', 'a', 'a', 'b', 'c', 'd', 'b'] + const currentOutput = tally(input) + const targetOutput = { a : 3, b: 2, c: 1, d: 1 } + expect(currentOutput).toEqual(targetOutput) +}); // Given an invalid input like a string // When passed to tally diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..24ad94155 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -8,22 +8,33 @@ function invert(obj) { const invertedObj = {}; + // console.log(Object.entries(obj)) for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; } +const result = invert({ a: 1, b: 2 }); +const expected = { '1': 'a', '2': 'b' }; -// a) What is the current return value when invert is called with { a : 1 } +console.assert(JSON.stringify(result) === JSON.stringify(expected), "It should return { '1': 'a', '2': 'b' }") +// 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", "b": "2"} // c) What does Object.entries return? Why is it needed in this program? + // Object.entries returns key-value pairs array within array. We needed to separate each key-value pair + // and we could swap them // d) Explain why the current return value is different from the target output + // Because right now we are not returning the value of the key, we are just adding new key(with the name key) + // to the invertedObj variable. To fix this, we need to use bracket to use the value of the variable key. + // Moreover, we need to swap the object key-value pair. // e) Fix the implementation of invert (and write tests to prove it's fixed!) diff --git a/Sprint-2/stretch/count-words.js b/Sprint-2/stretch/count-words.js index 8e85d19d7..9b2a4d93a 100644 --- a/Sprint-2/stretch/count-words.js +++ b/Sprint-2/stretch/count-words.js @@ -26,3 +26,32 @@ 3. Order the results to find out which word is the most common in the input */ + +function countWords(string) { + const punctuation = /[\.,?!]/g; // regular expression to check the following punctuation marks (".", ",", "!", "?") + const stringsIntoArray = string.replace(punctuation, "").toLowerCase().split(" "); // remove the punctuation (e.g. ".", ",", "!", "?") from the string and make the string in lower case then split each word as an element of the array + const wordObject = {}; // create an empty object {} + + for (const word of stringsIntoArray) { + if (wordObject[word]){ + wordObject[word] += 1; + } + else { + wordObject[word] = 1; + } + } + // Find the most common word (advanced step) + let mostCommonWord = ""; + let maxCount = 0; + for (const [word, count] of Object.entries(wordObject)) { + if (count > maxCount) { + maxCount = count; + mostCommonWord = word; + } + } + console.log("🚀 ~ countWords ~ mostCommonWord:", mostCommonWord) + + return wordObject + +} +console.log(countWords("You and me and you you!!!!!"), ) \ No newline at end of file diff --git a/Sprint-2/stretch/mode.js b/Sprint-2/stretch/mode.js index 3f7609d79..368e7b3d2 100644 --- a/Sprint-2/stretch/mode.js +++ b/Sprint-2/stretch/mode.js @@ -9,6 +9,11 @@ // into smaller functions using the stages above function calculateMode(list) { + const freqs = getFrequencies(list); + return getMostFrequentValue(freqs); +} + +function getFrequencies(list) { // track frequency of each value let freqs = new Map(); @@ -19,7 +24,9 @@ function calculateMode(list) { freqs.set(num, (freqs.get(num) || 0) + 1); } - + return freqs +} +function getMostFrequentValue(freqs) { // Find the value with the highest frequency let maxFreq = 0; let mode; @@ -32,5 +39,6 @@ function calculateMode(list) { return maxFreq === 0 ? NaN : mode; } +console.log(calculateMode([2, 4, 1, 2, 3, 2, 1])) module.exports = calculateMode; diff --git a/Sprint-2/stretch/till.js b/Sprint-2/stretch/till.js index 6a08532e7..f39691b97 100644 --- a/Sprint-2/stretch/till.js +++ b/Sprint-2/stretch/till.js @@ -8,24 +8,31 @@ function totalTill(till) { let total = 0; for (const [coin, quantity] of Object.entries(till)) { - total += coin * quantity; + total += coin.slice("0", coin.length - 1) * quantity; } return `£${total / 100}`; } const till = { - "1p": 10, - "5p": 6, - "50p": 4, - "20p": 10, + "1p": 10, + "5p": 6, + "50p": 4, + "20p": 10, }; const totalAmount = totalTill(till); + // a) What is the target output when totalTill is called with the till object + // is to return the total amounts in pounds which is in this example qual to £4.4 // b) Why do we need to use Object.entries inside the for...of loop in this function? + // to get each key-value pair alone and assign key to be = coin and value = quantity // c) What does coin * quantity evaluate to inside the for...of loop? + // multiplication of the key by the value // d) Write a test for this function to check it works and then fix the implementation of totalTill +const input = totalTill({"1p": 10}) +const targetOutput = "£0.1" +console.assert(input === targetOutput, "It should return £0.1") diff --git a/prep/array.js b/prep/array.js new file mode 100644 index 000000000..e146af6f0 --- /dev/null +++ b/prep/array.js @@ -0,0 +1,9 @@ +// declaring array literal as follows + +const items = [4.6, 5.9, 6.99]; + +// In JavaScript, we can use square bracket notation to access specific elements in the array using an index. + +items[0]; // evaluates to 4.6 +items[1]; // evaluates to 5.9 +items[2]; // evaluates to 6.99 \ No newline at end of file diff --git a/prep/assembling.the.parts.js b/prep/assembling.the.parts.js new file mode 100644 index 000000000..3feb6b233 --- /dev/null +++ b/prep/assembling.the.parts.js @@ -0,0 +1,11 @@ +const calculateMedian = require('./median'); +const calculateMean = require('./mean'); + +const salaries = [10, 20, 30, 40, 60, 80, 80]; +const median = calculateMedian(salaries); + +console.log(salaries, "<--- salaries input before we call calculateMean"); +const mean = calculateMean(salaries); + +console.log(`The median salary is ${median}`); +console.log(`The mean salary is ${mean}`); \ No newline at end of file diff --git a/prep/iteration.js b/prep/iteration.js new file mode 100644 index 000000000..1fd0c2122 --- /dev/null +++ b/prep/iteration.js @@ -0,0 +1,14 @@ +// In programming, the process of repeating something is called iteration. +// In programming, we can iterate by using a loop🧶 +// 🧶 loop: A loop is a sequence of instructions that is continually repeated until some condition is reached. +// In particular, we can use a for...of statement to sum the elements of the array. + +function calculateMean(list) { + let total = 0; + + for (const item of list) { + total += item; + } + +} +calculateMean([10, 20, 30, 40, 50]); \ No newline at end of file diff --git a/prep/mean.js b/prep/mean.js new file mode 100644 index 000000000..dde1fdcb2 --- /dev/null +++ b/prep/mean.js @@ -0,0 +1,8 @@ +function calculateMean(list) { + let total = 0; + for (const item of list) { + return total += item; + } +} + +module.exports = calculateMean; \ No newline at end of file diff --git a/prep/mean.test.js b/prep/mean.test.js new file mode 100644 index 000000000..75ea790ab --- /dev/null +++ b/prep/mean.test.js @@ -0,0 +1,15 @@ +// Let’s consider a problem where we calculate the mean of a list of numbers. + +// Given an array of numbers +// When we call calculateMean with the array of numbers +// Then we get the mean. + +const calculateMean = require('./median'); + +test("calculates the mean of a list of numbers", () => { + const list = [3, 50, 7]; + const currentOutput = calculateMean(list); + const targetOutput = 20; + + expect(currentOutput).toEqual(targetOutput); // 20 is (3 + 50 + 7) / 3 +}); diff --git a/prep/median.js b/prep/median.js new file mode 100644 index 000000000..b2cab619f --- /dev/null +++ b/prep/median.js @@ -0,0 +1,9 @@ +function calculateMedian(list) { + const middleIndex = Math.floor(list.length / 2); + const median = list.splice(middleIndex, 1)[0]; + + return median; + +} + +module.exports = calculateMedian; \ No newline at end of file diff --git a/prep/median.test.js b/prep/median.test.js new file mode 100644 index 000000000..f2ac18bbf --- /dev/null +++ b/prep/median.test.js @@ -0,0 +1,9 @@ +const calculateMedian = require('./median'); + +test("calculates the median of a list of odd length", () => { + const list = [10, 20, 30, 50, 60]; + const currentOutput = calculateMedian(list); + const targetOutput = 30; + + expect(currentOutput).toEqual(targetOutput); +}); \ No newline at end of file diff --git a/prep/summation.js b/prep/summation.js new file mode 100644 index 000000000..5d75951f3 --- /dev/null +++ b/prep/summation.js @@ -0,0 +1,16 @@ +// To sum a list we can start by creating a variable total with an initial value of 0. +// We then need to repeatedly add each value in the list to our total. + +function sumValues(list) { + let total = 0; + total += list[0]; // access a list element and add to total + total += list[1]; + total += list[2]; + total += list[3]; + total += list[4]; + return total; +} + +console.log(sumValues([1, 2, 3, 4, 5])); +// However, this approach is flawed. +