Skip to content

Conversation

HoussamLh
Copy link

@HoussamLh HoussamLh commented Sep 13, 2025

Self checklist

  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • My changes meet the requirements of the task
  • I have tested my changes
  • My changes follow the style guide

Changelist

1. Debug

  • Fixed issues in object property access and iteration:
  • Correctly logged object property values (author object)
  • Accessed specific properties instead of using incorrect indices (address object)
  • Logged array items within objects properly (recipe object)
  • Explanations and predictions added as comments in the code.

2. Implement

  • Implemented functions with corresponding tests:
  • contains(obj, prop) → checks if an object contains a specific property
  • createLookup(pairs) → builds a key-value lookup from an array of pairs
  • parseQueryString(queryString) → parses URL query strings, handles = in values, duplicates, and percent-decoding
  • tally(items) → counts occurrences of each item in an array
  • All tests cover normal cases and edge cases.

3. Interpret

  • invert(obj) → swaps keys and values of an object
  • Answers to questions (a → e) are included as comments explaining the original problem and the fix.

4. Stretch

  • countWords(str) → counts word occurrences in a string
  • Advanced: removes punctuation, ignores case, sorts results by frequency
  • calculateMode(list) → returns the most frequent number
  • Refactored into helper functions: buildFrequencyMap and findMode
  • totalTill(till) → calculates the total value of a till in pounds
  • Fixed parsing of coin strings (e.g., "50p" → 50), handles empty till
  • Tests added for all functions to validate expected behavior and edge cases.

Questions

  1. Why did for (const value of author) fail when iterating over an object?
  2. How does contains(obj, prop) check for the existence of a property?
  3. Why did invert({ a: 1, b: 2 }) originally return { key: 2 } instead of { "1": "a", "2": "b" }?
  4. Why did totalTill originally return NaN when multiplying coin * quantity?

Challenge Notes
1. Iterating over objects

  • I tried for (const value of author) but it failed because plain objects are not iterable.
  • Fix: use for...in for keys, or Object.keys() / Object.values() / Object.entries() with for...of.

2. contains(obj, prop) behavior

  • At first, I used Object.prototype.hasOwnProperty.call(obj, prop) to check for own properties.
  • Mentor suggested the cleaner Object.hasOwn(obj, prop).
  • Assumption: contains() should check own properties only, not inherited ones.

3. invert({ a: 1, b: 2 }) bug

  • The original code returned { key: 2 } because I mistakenly wrote result.key = obj[key].
  • Dot notation created a literal "key" property instead of using the variable.
  • Fix: use bracket notation → result[obj[key]] = key;.

4. totalTill returning NaN

  • The expression coin * quantity failed because coin was a string like "20p".
  • Multiplying "20p" * 3 results in NaN.
  • Fix: parse the coin into a number first:
    const coinValue = parseInt(coin, 10);
    total += coinValue * quantity;

@HoussamLh HoussamLh added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Sep 13, 2025
Copy link
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.

Code is very solid! I only have a few suggestions.

}

// Use Object.prototype.hasOwnProperty to check if property exists
return Object.prototype.hasOwnProperty.call(obj, prop);
Copy link
Contributor

Choose a reason for hiding this comment

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

There is another (more compact) function in Object we can use. Can you find out how we can rewrite line 8 with less code.

Copy link
Author

Choose a reason for hiding this comment

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

Hi cjyuan,
Thank you for the feedback!
I updated the code to use Object.hasOwn(obj, prop) instead of Object.prototype.hasOwnProperty.call(obj, prop).
It’s definitely more compact and readable.

Comment on lines 6 to 8
const result = {};
for (const item of items) {
if (Object.prototype.hasOwnProperty.call(result, item)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a way to create an empty object with no inherited properties.

If result is such an object, then we can simplify line 8 as if (result[item]) {.

Copy link
Author

Choose a reason for hiding this comment

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

Hi cjyuan,
Thank you for pointing this out!
I changed result = {} to result = Object.create(null), so the object has no inherited properties. This allowed me to simplify the condition to if (result[item]) { as suggested.

Comment on lines 49 to 60
const counts = {};

// 1. Remove punctuation
const noPunctuation = str.replace(/[.,!?]/g, "");

// 2. Ignore case
const words = noPunctuation.toLowerCase().split(/\s+/);

for (const word of words) {
if (!word) continue; // skip empty strings
counts[word] = (counts[word] || 0) + 1;
}
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 this function returns what you expect in the following function call?

countWords("constructor constructor");

Copy link
Author

Choose a reason for hiding this comment

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

Hi cjyuan,
Thanks for your guidence.
I tested with "constructor constructor" and saw the issue. I updated counts to use Object.create(null) instead of {}, so now the function correctly returns { constructor: 2 }.

total += coin * quantity;
// coin is a string like "1p", "20p"
// We need to strip the "p" and convert it into a number of pennies
const coinValue = parseInt(coin.replace("p", ""), 10);
Copy link
Contributor

Choose a reason for hiding this comment

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

We could also rewrite line 13 as:
const coinValue = parseInt(coin);

Can you figure out why?

Copy link
Author

Choose a reason for hiding this comment

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

Hi cjyuan,
Thanks! I see why — parseInt("20p", 10) returns 20 since it stops parsing at the "p".
That makes .replace("p", "") unnecessary, so I simplified the 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 Sep 13, 2025
@cjyuan
Copy link
Contributor

cjyuan commented Sep 14, 2025

Why did for (const value of author) fail when iterating over an object?

Have you try asking AI?

How does contains(obj, prop) check for the existence of a property?

The spec was not clear how contains() should check for the existence of a property. When the spec is not clear, we can either ask for clarification (especially when the ambiguity can lead to serious consequence) or make reasonable assumption and write down our assumption.

Why did invert({ a: 1, b: 2 }) originally return { key: 2 } instead of { "1": "a", "2": "b" }?

It seems you had figured out the answer.

Why did totalTill originally return NaN when multiplying coin * quantity?

You can also try AI for questions like this. :)

@HoussamLh HoussamLh added Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. and removed Reviewed Volunteer to add when completing a review with trainee action still to take. labels Sep 14, 2025
@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. labels Sep 14, 2025
@cjyuan
Copy link
Contributor

cjyuan commented Sep 14, 2025

Everything looks great. Well done!

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.

2 participants