Skip to content

Sheffield | 26-ITP-Jan | Mahmoud Shaabo | Sprint 2 | Module-Data-Groups#1069

Closed
mahmoudshaabo1984 wants to merge 3 commits into
CodeYourFuture:mainfrom
mahmoudshaabo1984:sprint-2-exercises
Closed

Sheffield | 26-ITP-Jan | Mahmoud Shaabo | Sprint 2 | Module-Data-Groups#1069
mahmoudshaabo1984 wants to merge 3 commits into
CodeYourFuture:mainfrom
mahmoudshaabo1984:sprint-2-exercises

Conversation

@mahmoudshaabo1984
Copy link
Copy Markdown

Hello Reviewers / CodeYourFuture Team,

I have completed all mandatory and stretch exercises for Sprint 2. I made sure to thoroughly test my code, handle edge cases, and apply refactoring best practices.

Here is a summary of the progress:

  • Debug: Successfully fixed the bugs in address.js, author.js, and recipe.js by utilizing proper object iteration (Object.entries, Object.values) and correct property access.
  • Implement: Implemented the logic for contains, lookup, and tally. I also fixed the querystring function using indexOf("=") and slice() to correctly handle multiple equal signs securely.
  • Interpret: Refactored invert.js using bracket notation to dynamically assign keys and values. All analytical questions (a-e) have been clearly answered in the comments.
  • Stretch (Advanced): - count-words.js: Implemented Regex to remove punctuation, handled case insensitivity, and sorted the final results by frequency.
    • mode.js: Successfully refactored the function into two smaller, single-responsibility functions (countFrequencies and findHighestFrequency) utilizing the Map object.
    • till.js: Fixed the NaN bug by using parseInt() to accurately extract numerical values from strings.

Testing: Verified that all tests across all folders pass successfully using npx jest and manual node testing.

Personal Note for the Team:
Working with Map, Object.entries(), and data type parsing in this sprint greatly improved my understanding of how to safely manipulate complex objects in JavaScript. I have also ensured all my comments explain the "why" behind the code to be fully screen-reader compatible. I look forward to your feedback!

Best regards,
Mahmoud Shaabo

@mahmoudshaabo1984
Copy link
Copy Markdown
Author

Hi CJ,

I have just submitted my Pull Request for the Sprint 2 exercises. I really enjoyed the challenges in this sprint, especially learning how to refactor functions and using tools like Map, Object.entries(), and parseInt() to handle data safely.

All tests are passing, and I made sure my comments clearly explain the logic behind the code.

I am looking forward to your review and any feedback or suggestions you might have.

Thank you!

@mahmoudshaabo1984 mahmoudshaabo1984 added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Mar 22, 2026
Copy link
Copy Markdown
Contributor

@cjyuan cjyuan left a comment

Choose a reason for hiding this comment

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

This exercise also expects the .test.js files in the "implement" folder to be updated. There are tests to be implemented.

Comment thread Sprint-2/debug/recipe.js
Comment on lines +17 to +19
for (const ingredient of recipe.ingredients) {
console.log(ingredient);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your code works.

Here is an alternative worth exploring:
Since ingredient values are separated by '\n' in the output, we could also use
Array.prototype.join() to construct the equivalent string and then output the resulting string.

Comment on lines +15 to +27
// Find the position of the FIRST "=" only
const firstEqualIndex = pair.indexOf("=");

// If there is no "=", the whole pair is the key with an empty value
if (firstEqualIndex === -1) {
queryParams[pair] = "";
} else {
// Everything before the first "=" is the key
const key = pair.slice(0, firstEqualIndex);
// Everything after the first "=" is the value (may contain more "=" signs)
const value = pair.slice(firstEqualIndex + 1);
queryParams[key] = value;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does your function return the value you expect from the following function call?

parseQueryString("key1=value1&&key2=value2")

Comment thread Sprint-2/implement/tally.js Outdated
Comment on lines +9 to +17
const counts = {};

// Loop through each item in the array
for (const item of items) {
// If this item already exists in counts, add 1 to it
// If it does not exist yet, start at 1
counts[item] = (counts[item] || 0) + 1;
}

Copy link
Copy Markdown
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"]);

Suggestion: Look up an approach to create an empty object with no inherited properties.

Comment thread Sprint-2/stretch/count-words.js Outdated
Comment on lines +56 to +59
const sortedCounts = {};
for (const [word, count] of sorted) {
sortedCounts[word] = count;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can also explore using Object.fromEntries() to simplify the code.

Comment thread Sprint-2/stretch/mode.js Outdated
Comment on lines 12 to 14
let freqs = new Map();

for (let num of list) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could also consider replacing let by const to further improving the original code.

@cjyuan cjyuan added Reviewed Volunteer to add when completing a review with trainee action still to take. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Mar 25, 2026
@mahmoudshaabo1984 mahmoudshaabo1984 added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Mar 28, 2026
…ing edge case

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mahmoudshaabo1984
Copy link
Copy Markdown
Author

Hi CJ,

Thank you for the detailed review! I have addressed all your feedback. Here is a summary of the changes:

Mandatory fixes:

  1. tally.js — Changed const counts = {}; to const counts = Object.create(null); to avoid inherited prototype properties like toString. Now tally(["toString", "toString"]) correctly returns { toString: 2 }.

  2. querystring.js — Added a check to skip empty pairs (if (pair === "") continue;) inside the loop. Now parseQueryString("key1=value1&&key2=value2") correctly ignores the empty string between the double ampersands.

  3. contains.test.js — Replaced test.todo with 4 real tests: empty object returns false, existing property returns true, non-existent property returns false, and array input returns false.

  4. lookup.test.js — Replaced test.todo with 3 real tests: multiple pairs, single pair, and empty array.

  5. tally.test.js — Replaced test.todo with 4 real tests: empty array, duplicate items, string input throws error, and items named "toString" are counted correctly.

Optional improvements (also applied):

  1. count-words.js — Replaced the manual loop with Object.fromEntries(sorted) as you suggested.

  2. mode.js — Changed let to const for freqs and the for...of loop variables, since they are not reassigned.

All 15 tests pass across implement/ and stretch/.

Looking forward to your feedback!

Best regards,
Mahmoud Shaabo

Copy link
Copy Markdown
Contributor

@cjyuan cjyuan left a comment

Choose a reason for hiding this comment

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

All other changes look good.

Comment on lines +44 to +46
test("contains returns false when passed an array instead of an object", () => {
expect(contains(["a", "b"], "a")).toBe(false);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This test does not yet confirm that the function correctly returns false when the first argument is an array.
This is because contains(["a", "b"], "a") could also return false simply because "a" is not a key of the array.

Arrays are objects, with their indices acting as keys. A proper test should use a valid
key to ensure the function returns false specifically because the input is an array, not because the key is missing.

@cjyuan cjyuan removed the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Mar 28, 2026
@mahmoudshaabo1984
Copy link
Copy Markdown
Author

Hi CJ,

Great catch — you are absolutely right. The previous test was passing for the wrong reason.

I have updated the test to use a valid array index as the key:

expect(contains(["a", "b"], "0")).toBe(false);

Since "0" is a valid key in the array, the only reason this returns false is because the function correctly rejects arrays. This properly confirms the intended behaviour.

All tests are passing. Thank you for the thorough review — I learned something important about writing meaningful tests!

Best regards,
Mahmoud

@mahmoudshaabo1984 mahmoudshaabo1984 added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Mar 28, 2026
@cjyuan
Copy link
Copy Markdown
Contributor

cjyuan commented Mar 28, 2026

Changes look good. Well done.

@cjyuan cjyuan added Complete Volunteer to add when work is complete and all review comments have been addressed. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. Reviewed Volunteer to add when completing a review with trainee action still to take. labels Mar 28, 2026
@illicitonion
Copy link
Copy Markdown
Member

Closing PR because the January ITP run has finished. Feel free to re-open if you're still working on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Complete Volunteer to add when work is complete and all review comments have been addressed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants