Skip to content

Sheffield | 25-ITP-May | Declan Williams | Data-Groups-Sprint-2 #696

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ca796ca
added comments for my prediction and given suggestion
CatchingKiyoko Jul 5, 2025
87aa2f8
Fix console log to correctly display house number from address object
CatchingKiyoko Jul 5, 2025
b586c5d
added comments predicting and expecting to happen and given reasons t…
CatchingKiyoko Jul 5, 2025
3d8c0e4
Fix error by using Object.values() in for...of loop
CatchingKiyoko Jul 5, 2025
0c740e3
Add comments to explain expected behavior and necessary fixes for ing…
CatchingKiyoko Jul 5, 2025
996a55e
refactored code in console log to correctly call ingredients to the c…
CatchingKiyoko Jul 5, 2025
cbcab13
Refactor parseQueryString to handle values with "=" by splitting only…
CatchingKiyoko Jul 9, 2025
53b286f
added tests to cover parses keys with multiple "=" signs
CatchingKiyoko Jul 9, 2025
88ad32f
Add test for parsing querystring with no value
CatchingKiyoko Jul 9, 2025
60d9b7c
added comments answering questions around the function invert
CatchingKiyoko Jul 9, 2025
2307da8
Fix implementation of invert function to correctly swap keys and values
CatchingKiyoko Jul 9, 2025
ac0ffda
implemented parameters to contains function and to check if obj is an…
CatchingKiyoko Jul 11, 2025
339ddd7
added jest test: for when an empty object is passed into contains fun…
CatchingKiyoko Jul 11, 2025
b96968f
Fix type check for object in contains function
CatchingKiyoko Jul 11, 2025
228755f
fix: add missing return false to handle cases where key is not found
CatchingKiyoko Jul 11, 2025
370b07c
implemented: loop through object keys using for...in
CatchingKiyoko Jul 11, 2025
3b15131
added test case for contains function to verify it returns true for e…
CatchingKiyoko Jul 11, 2025
b7b0215
refactor: update test descriptions for clarity and consistency and ad…
CatchingKiyoko Jul 11, 2025
8f6fe97
added test case for when invalid parameters like an array
CatchingKiyoko Jul 11, 2025
6742902
initialize results object in createLookup function
CatchingKiyoko Jul 22, 2025
c3764f5
implemented parameter to createLookup function and correct result var…
CatchingKiyoko Jul 22, 2025
7525314
fix: correct variable name from 'result' to 'results' in createLookup…
CatchingKiyoko Jul 22, 2025
84e8552
test: implement test for country currency code lookup functionality
CatchingKiyoko Jul 22, 2025
a11cbcd
test: add test case for returning an empty object with an empty array
CatchingKiyoko Jul 22, 2025
9539ce3
implement input validation for tally function to ensure array input
CatchingKiyoko Jul 24, 2025
a257896
added a empty object to store counted items
CatchingKiyoko Jul 24, 2025
79afe87
implemented jest test for if function(Tally) is given an empty array
CatchingKiyoko Jul 24, 2025
0da94ce
Add for...of loop to count how many times each item appears in array
CatchingKiyoko Jul 24, 2025
2a37e5e
added jest test for when a given array has duplicate items
CatchingKiyoko Jul 24, 2025
430f315
added jest test for a given invalid input
CatchingKiyoko Jul 24, 2025
08460b7
Merge branch 'main' into Data-Groups-Sprint-2
CatchingKiyoko Jul 24, 2025
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
8 changes: 7 additions & 1 deletion Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -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...
Expand All @@ -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
8 changes: 7 additions & 1 deletion Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -11,6 +17,6 @@ const author = {
alive: true,
};

for (const value of author) {
for (const value of Object.values(author)){
console.log(value);
}
8 changes: 5 additions & 3 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
// 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",
serves: 2,
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[0]}\n ${recipe.ingredients[1]}\n ${recipe.ingredients[2]}\n ${recipe.ingredients[3]}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you modify this code so that it still works if we change the number of ingredients?

13 changes: 12 additions & 1 deletion Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -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" || 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;
}
Comment on lines +6 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion
You may want to check out the following two approaches for determining if an object contains a property:

  let obj = {}, propertyName = "toString";
  console.log( propertyName in obj );                // true
  console.log( Object.hasOwn(obj, propertyName) );   // false

For more info, you can look up JS "in" operator vs Object.hasOwn.


return false; // if no object or key is found return false
}
module.exports = contains;
15 changes: 13 additions & 2 deletions Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check if your function can pass this test?
expect(contains(null, "a").toBe(false);

});
11 changes: 10 additions & 1 deletion Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -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;
10 changes: 8 additions & 2 deletions Sprint-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
7 changes: 6 additions & 1 deletion Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Comment on lines +14 to 16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that in real querystring, both key and value are percent-encoded or URL encoded in the URL. For example, the string "5%" will be encoded as "5%25". So to get the actual value of "5%25" (whether it is a key or value in the querystring), you should call a function to decode it.
May I suggest looking up any of these terms, and "How to decode URL encoded string in JS"?


Expand Down
12 changes: 12 additions & 0 deletions Sprint-2/implement/querystring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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": "",
});
});
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(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 = {};

// 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;
}
Comment on lines +1 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the following function call returns the value you expect?

tally(["toString", "toString"]);


module.exports = tally;
10 changes: 9 additions & 1 deletion Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
19 changes: 18 additions & 1 deletion Sprint-2/interpret/invert.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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;
}