Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
b27b10f
predicted and explaint what will happen
Tobias-Amaechina Jul 23, 2026
f017ce1
fix the bracket notation to access the key property of the onject an…
Tobias-Amaechina Jul 23, 2026
e5e37a2
made a prediction with my reason on what will happen when the progra…
Tobias-Amaechina Jul 24, 2026
ae5347b
I used for ..in and bracket notation to access the properties value …
Tobias-Amaechina Jul 24, 2026
d8493ef
made my prediction as to what will happen when the program runs and…
Tobias-Amaechina Jul 24, 2026
01748e7
used for .. of to iterate over the aray elemnts in the ingredient an…
Tobias-Amaechina Jul 24, 2026
2e7ce33
Wrote a test to check for property name in given object and return t…
Tobias-Amaechina Jul 24, 2026
0ace00d
implements a function to pass the test
Tobias-Amaechina Jul 24, 2026
bd7b8a3
Wrote a test to check for name property from an empty array and retu…
Tobias-Amaechina Jul 24, 2026
7995cac
Re-write the General acceptance criteria to a separate test for when…
Tobias-Amaechina Jul 24, 2026
d0d5b6c
Wrote a test to return false when invalid parameters like array are p…
Tobias-Amaechina Jul 24, 2026
105c0e7
wrote a test check and return false when string is passed
Tobias-Amaechina Jul 24, 2026
931be76
Wrote a test to check and return false when invalid parameter like nu…
Tobias-Amaechina Jul 24, 2026
96db9d3
commented out the test.todo
Tobias-Amaechina Jul 24, 2026
e07fc92
wrote a test suite to check for multiple array , empty array and sing…
Tobias-Amaechina Jul 24, 2026
c6fad45
Implemented a function to pass the test of country and currency code
Tobias-Amaechina Jul 24, 2026
311f34a
refatored the consitional statement to check for empty string ,also …
Tobias-Amaechina Jul 27, 2026
502af08
repaced the occurence of plus sign with spaces
Tobias-Amaechina Jul 27, 2026
1e8578b
separated the key, value at the first occurance of "="
Tobias-Amaechina Jul 27, 2026
4ea0c56
replace const with let to allow for reassigment in the for .. of loop…
Tobias-Amaechina Jul 27, 2026
a404823
created an empty array
Tobias-Amaechina Jul 27, 2026
a76b2fd
declare the items vatiable and validate if it has anything at all
Tobias-Amaechina Jul 27, 2026
2ebe778
Validate the inpute data corectly with the correct name to ensure the…
Tobias-Amaechina Jul 27, 2026
30b4cdd
declare the variable frequency an assign it empty object
Tobias-Amaechina Jul 27, 2026
8c60483
wrote the test suite for the test cases
Tobias-Amaechina Jul 27, 2026
5683e38
answered the first question a
Tobias-Amaechina Jul 27, 2026
1760ba2
answered the questin for b
Tobias-Amaechina Jul 27, 2026
55dd8a5
gave the correct response for the question a
Tobias-Amaechina Jul 27, 2026
0b3d681
answered question about what the target return should be
Tobias-Amaechina Jul 27, 2026
7757d5f
Answered question on what Object.entries does
Tobias-Amaechina Jul 27, 2026
82dbb8a
Answered the question for d
Tobias-Amaechina Jul 27, 2026
2d3c86d
fixed the implementation to invert the returned value
Tobias-Amaechina Jul 27, 2026
4de7d6b
implemented the function
Tobias-Amaechina Jul 27, 2026
e75e0c5
created an empty file invert.test.js
Tobias-Amaechina Jul 27, 2026
61b2205
deleted the console.assert and exported the function invert
Tobias-Amaechina Jul 27, 2026
d50ad7f
wrote a test to passed the implemetion
Tobias-Amaechina Jul 27, 2026
f350f5e
removed the second tally.js file import from the tall.test.js file
Tobias-Amaechina Jul 27, 2026
3985d77
Declare a function with a name countWords
Tobias-Amaechina Jul 27, 2026
b6d6732
give the function declaration a parameter and validate that it's a s…
Tobias-Amaechina Jul 27, 2026
9f5ff0b
use regex to replace any puncuations with empty string
Tobias-Amaechina Jul 27, 2026
bc5e948
split the cleanedStr and filler words that passed the condition
Tobias-Amaechina Jul 27, 2026
5940b72
ordered the words by sorting them
Tobias-Amaechina Jul 27, 2026
e4257fc
Refactored the code to have two stages ! to track frequency of each …
Tobias-Amaechina Jul 27, 2026
1dcd83a
Answered the quest a
Tobias-Amaechina Jul 27, 2026
73823dc
Answere question b
Tobias-Amaechina Jul 27, 2026
62439d4
Answered question c what the calculation evaluated to inside the for …
Tobias-Amaechina Jul 27, 2026
7ecfd73
Wrote a test to check if the implementation worked
Tobias-Amaechina Jul 27, 2026
7a9a51d
Implement the function to pass the test
Tobias-Amaechina Jul 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Predict and explain first...
// Predict and explain first.../* there will be output of undefined as we are trying to access a property that is not yet defined

// This code should log out the houseNumber from the address object
// but it isn't working...
Expand All @@ -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"]}`);
7 changes: 4 additions & 3 deletions Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Predict and explain first...
// My prediction is that there will be a TypeError as for ..of loop that is meant for array like object is being used on an object literals to access it's properties

// 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
Expand All @@ -11,6 +12,6 @@ const author = {
alive: true,
};

for (const value of author) {
console.log(value);
}
for (const value in author) {
console.log(author[value]);
}
11 changes: 8 additions & 3 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Predict and explain first...
/* my prediction is that this program will print the title and how many it services but not the ingrientes as there is no dot notation in the recipe expression so the properties are never accessed */

// This program should log out the title, how many it serves and the ingredients.
// Each ingredient should be logged on a new line
Expand All @@ -10,6 +11,10 @@ const recipe = {
ingredients: ["olive oil", "tomatoes", "salt", "pepper"],
};

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
console.log(`${recipe.title} serves ${recipe.serves}`);
console.log("ingredients:");
// use for of to print the value of the ingredients array element
for (const ingredients of recipe.ingredients){
console.log(ingredients);
};

9 changes: 8 additions & 1 deletion Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
function contains() {}

function contains(obj, target) {
for (const key in obj) {
if (key === target) return true;
}
return false;
}


module.exports = contains;
30 changes: 27 additions & 3 deletions Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,44 @@ as the object doesn't contains a key of 'c'
// Given a contains function
// When passed an object and a property name
// Then it should return true if the object contains the property, false otherwise

//Case 1
test(" Case 1: returns true when the property exists", () => {
expect(contains({ a: 1, b: 2 }, "a")).toBe(true);
});

test("Case 2: returns false when the property does not exist", () => {
expect(contains({ a: 1, b: 2 }, "c")).toBe(false);
});
// 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({ }, "c")).toBe(false);});

// Given an object with properties
// When passed to contains with an existing property name
// Then it should return true
test(" Case 1: returns true when the property exists", () => {
expect(contains({ a: 1, b: 2 }, "a")).toBe(true);
});

// Given an object with properties
// When passed to contains with a non-existent property name
// Then it should return false

test("Case 2: returns false when the property does not exist", () => {
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(" returns false when invalid parameters like arrays are passed ", () => {
expect(contains([1,"a","NaN","b","3"], "a")).toBe(false);
});
test(" returns false when invalid parameters like String is passed ", () => {
expect(contains("Toby", "Toby")).toBe(false);
});

test(" returns false when invalid parameters like number is passed ", () => {
expect(contains(1, 1)).toBe(false);
});
9 changes: 8 additions & 1 deletion Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
function createLookup() {
function createLookup(pairs) {
const lookup = {};

for (let [country, currency] of pairs) {
lookup[country] = currency;
}

return lookup;
// implementation here
}

Expand Down
27 changes: 26 additions & 1 deletion Sprint-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const createLookup = require("./lookup.js");

test.todo("creates a country currency code lookup for multiple codes");
//test.todo("creates a country currency code lookup for multiple codes");

/*

Expand Down Expand Up @@ -33,3 +33,28 @@ It should return:
'CA': 'CAD'
}
*/
describe("createLookup", () => {
test("creates a country currency code lookup for multiple codes", () => {
const input = [
["US", "USD"],
["CA", "CAD"],
["GB", "GBP"],
];

const result = createLookup(input);

expect(result).toEqual({
US: "USD",
CA: "CAD",
GB: "GBP",
});
});

test("returns an empty object when given an empty array", () => {
expect(createLookup([])).toEqual({});
});

test("handles a single pair correctly", () => {
expect(createLookup([["JP", "JPY"]])).toEqual({ JP: "JPY" });
});
});
37 changes: 30 additions & 7 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
function parseQueryString(queryString) {
const queryParams = {};
if (queryString.length === 0) {
return queryParams;
}
const keyValuePairs = queryString.split("&");
if (!queryString) return queryParams;

const keyValuePairs = queryString.split("&").filter((item) => item !== "");

for (let pair of keyValuePairs) {
// Replace '+' with spaces
pair = pair.replace(/\+/g, " ");

const eqIdx = pair.indexOf("=");

let keyPair, valuePair;

if (eqIdx === -1) {
keyPair = pair;
valuePair = "";
} else {
keyPair = pair.slice(0, eqIdx);
valuePair = pair.slice(eqIdx + 1);
}

const key = decodeURIComponent(keyPair);
const value = decodeURIComponent(valuePair);

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
// Handle duplicates
if (!(key in queryParams)) {
queryParams[key] = value;
} else if (Array.isArray(queryParams[key])) {
queryParams[key].push(value);
} else {
queryParams[key] = [queryParams[key], value];
}
}

return queryParams;
Expand Down
19 changes: 18 additions & 1 deletion Sprint-2/implement/tally.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
function tally() {}
function tally(items) {
if(!Array.isArray(items)){
throw new Error("Input must me and array");
// validate and throw error if input is not an array .
}
const frequency = {};
for (let item of items){
if (item in frequency){
frequency[item] +=1;
}else{
frequency[item] = 1
}

}


return frequency;
}

module.exports = tally;
24 changes: 24 additions & 0 deletions Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,27 @@ test.todo("tally on an empty array returns an empty object");
// Given an invalid input like a string
// When passed to tally
// Then it should throw an error



describe("tally()", () => {
test("counts frequency of each unique item", () => {
const result = tally(["a", "a", "b", "c"]);
expect(result).toEqual({ a: 2, b: 1, c: 1 });
});
test("returns an empty object when given an empty array", () => {
expect(tally([])).toEqual({});
});

test("counts a single item correctly", () => {
expect(tally(["x"])).toEqual({ x: 1 });
});

test("throws an error when input is not an array", () => {
expect(() => tally("hello")).toThrow(Error);
expect(() => tally(123)).toThrow(Error);
expect(() => tally({})).toThrow(Error);
expect(() => tally(null)).toThrow(Error);
});
});

13 changes: 7 additions & 6 deletions Sprint-2/interpret/invert.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ function invert(obj) {
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 }
// 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 }
// b) What is the current return value when invert is called with { a: 1, b: 2 }// the current returned value is {key:2}

// c) What is the target return value when invert is called with {a : 1, b: 2}
// c) What is the target return value when invert is called with {a : 1, b: 2}// the target output is { '1': 'a', '2': 'b' }

// c) What does Object.entries return? Why is it needed in this program?
// c) What does Object.entries return? Why is it needed in this program?// Object.entries converts the object into an array of [key, value] pairs.

// d) Explain why the current return value is different from the target output
// d) Explain why the current return value is different from the target output// Because after iterations the "invertedObj.key=value" is assigning same value to the new variable name "key" with the dot notation.

// e) Fix the implementation of invert (and write tests to prove it's fixed!)
9 changes: 9 additions & 0 deletions Sprint-2/interpret/invert.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@


const invert = require("./invert.js");

test("swaps keys and values for a simple object", () => {
const input = { x: 10, y: 20 };
const output = invert(input);
expect(output).toEqual({ 10: "x", 20: "y" });
});
18 changes: 18 additions & 0 deletions Sprint-2/stretch/count-words.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,21 @@

3. Order the results to find out which word is the most common in the input
*/
function countWords(str){
if(typeof str !=="string"){
throw new Error("Input must be a string");
}
const cleanedStr = str.replace(/[.,!?;:]/g, "").toLowerCase();
const freq = {};
const words = cleanedStr.split(" ").filter((w) => w !== "");

for (const word of words) {
freq[word] = (freq[word] || 0) + 1;
}
const sorted = Object.entries(freq).sort((a, b) => b[1] - a[1]);

return sorted;
}



24 changes: 16 additions & 8 deletions Sprint-2/stretch/mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,24 @@
// refactor calculateMode by splitting up the code
// into smaller functions using the stages above

function calculateMode(list) {
// track frequency of each value
let freqs = new Map();
function buildFrequencyMap(list) {
const freqs = new Map();

for (let num of list) {
for (const num of list) {
if (typeof num !== "number") {
continue;
continue; // ignore non-numbers
}

freqs.set(num, (freqs.get(num) || 0) + 1);
}

// Find the value with the highest frequency
return freqs;
}

function findModeFromFreqs(freqs) {
let maxFreq = 0;
let mode;
for (let [num, freq] of freqs) {

for (const [num, freq] of freqs) {
if (freq > maxFreq) {
mode = num;
maxFreq = freq;
Expand All @@ -33,4 +35,10 @@ function calculateMode(list) {
return maxFreq === 0 ? NaN : mode;
}

function calculateMode(list) {
const freqs = buildFrequencyMap(list); // Stage 1
const mode = findModeFromFreqs(freqs); // Stage 2
return mode;
}

module.exports = calculateMode;
20 changes: 15 additions & 5 deletions Sprint-2/stretch/till.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ function totalTill(till) {
let total = 0;

for (const [coin, quantity] of Object.entries(till)) {
total += coin * quantity;
const coinValue = parseInt(coin);
total += coinValue * quantity;
}

return `£${total / 100}`;
return `£${(total / 100).toFixed(2)}`;
}

const till = {
Expand All @@ -22,10 +23,19 @@ const till = {
};
const totalAmount = totalTill(till);

// a) What is the target output when totalTill is called with the till object
const result = totalAmount;
const expectedResult = "£4.40";

// b) Why do we need to use Object.entries inside the for...of loop in this function?
if (result === expectedResult) {
console.log("✅ Test Passed!");
} else {
console.log(`❌ Test Failed. Expected ${expectedResult} but got ${result}`);
}

// a) What is the target output when totalTill is called with the till object/* the target output is (1p*10 + 5p*6 +50p*4 +20p*10) =440/100 = £4.40*/

// b) Why do we need to use Object.entries inside the for...of loop in this function?// we use Object.entries to convert Object into an arrays of array to enable iteration as javaScript object is not iterable*/

// c) What does coin * quantity evaluate to inside the for...of loop?
// c) What does coin * quantity evaluate to inside the for...of loop?/* The expression coin * quantity evaluated to NaN ,as Object.entries converted the object properties to string and after looping through , when the name Variable which is a string multiples a number they will concatenate to form NaN*/

// d) Write a test for this function to check it works and then fix the implementation of totalTill
Loading