-
-
Notifications
You must be signed in to change notification settings - Fork 313
Manchester | 26-ITP-May | Joanne O'Malley | Sprint 2 | Exercises #1247
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
base: main
Are you sure you want to change the base?
Changes from all commits
ca2ad9f
4048bc9
d91daaa
cc230d3
5325eb4
8ed4137
caa3679
06a8a41
0eed554
c5fc82b
32a8ef2
47caa8c
a0c4329
896e52b
f8ce3aa
aaeb462
99d8442
ca1fe4e
13a400e
91fc572
47c562d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| function contains() {} | ||
| function contains(obj, property_name) { | ||
| return Object.prototype.hasOwnProperty.call(obj, property_name); | ||
| } | ||
|
|
||
| module.exports = contains; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,11 @@ | ||
| function createLookup() { | ||
| function createLookup(country_currency_pairs) { | ||
| // implementation here | ||
| const lookup = {}; | ||
| for (const [country, currency] of country_currency_pairs) { | ||
| lookup[country] = currency; | ||
| } | ||
|
|
||
| return lookup; | ||
| } | ||
|
|
||
| module.exports = createLookup; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,25 @@ | ||
| function parseQueryString(queryString) { | ||
| const queryParams = {}; | ||
| if (queryString.length === 0) { | ||
| return queryParams; | ||
| } | ||
| const keyValuePairs = queryString.split("&"); | ||
| if (queryString === "") { | ||
| return {}; | ||
| } else { | ||
| queryString = decodeURIComponent(queryString) | ||
| .replace(/\+/g, " ") | ||
| .replace(/&&/g, "&") | ||
| .replace(/&+$/, ""); | ||
|
|
||
| for (const pair of keyValuePairs) { | ||
| const [key, value] = pair.split("="); | ||
| queryParams[key] = value; | ||
| } | ||
| const splitByAnds = queryString.split("&"); | ||
|
|
||
| const splitByEquals = splitByAnds.map(x => { | ||
| const match = x.match(/^([^=]*)(?:=(.*))?$/); | ||
|
|
||
| return queryParams; | ||
| const key = match[1]; | ||
| const value = match[2] ?? ""; | ||
|
|
||
| return [key, value]; | ||
| }); | ||
|
|
||
| return Object.fromEntries(splitByEquals); | ||
| } | ||
| } | ||
|
|
||
| module.exports = parseQueryString; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,16 @@ | ||
| function tally() {} | ||
| function tally(items) { | ||
| if (!Array.isArray(items)) { | ||
| throw new TypeError("Input must be an array"); | ||
| } | ||
|
|
||
| const uniqueItems = [...new Set(items)].sort(); | ||
|
|
||
| const counts = {}; | ||
| for (const item of uniqueItems) { | ||
| counts[item] = items.filter(x => x === item).length; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Imagine I had the input of
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current solution loops through the array once to build the unique list, then runs .filter() for each unique item. If the array contains only duplicates like ['a', 'a', 'a'], the set reduces it to ['a'], so .filter() only runs once. This gives us O(n). If every item is unique, .filter() runs once for every item in the array, and each filter scans the whole array again. This gives us O(n²). A more efficient approach is to loop through the array once and store the counts as we go using an object or dictionary. |
||
| } | ||
|
|
||
| return counts; | ||
| } | ||
|
|
||
| module.exports = tally; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| const invert = require("./invert.js"); | ||
|
|
||
| /* | ||
| Implement a function called invert that swaps the keys and values of an object. | ||
|
|
||
| E.g. invert({ x: 10, y: 20 }) | ||
| // returns { "10": "x", "20": "y" } | ||
| */ | ||
|
|
||
| // Acceptance criteria: | ||
|
|
||
| // Given an empty object | ||
| // When passed to invert | ||
| // Then it should return an empty object | ||
| test("returns an empty object when given an empty object", () => { | ||
| expect(invert({})).toEqual({}); | ||
| }); | ||
|
|
||
| // Given an object with one property | ||
| // When passed to invert | ||
| // Then it should swap the key and value | ||
| test("inverts an object with one key-value pair", () => { | ||
| expect(invert({ a: 1 })).toEqual({ | ||
| "1": "a", | ||
| }); | ||
| }); | ||
|
|
||
| // Given an object with multiple properties | ||
| // When passed to invert | ||
| // Then it should swap all keys and values | ||
| test("inverts an object with multiple key-value pairs", () => { | ||
| expect(invert({ a: 1, b: 2 })).toEqual({ | ||
| "1": "a", | ||
| "2": "b", | ||
| }); | ||
| }); | ||
|
|
||
| // Given an object with string values | ||
| // When passed to invert | ||
| // Then it should swap the keys and values | ||
| test("inverts string values correctly", () => { | ||
| expect(invert({ first: "apple", second: "banana" })).toEqual({ | ||
| apple: "first", | ||
| banana: "second", | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain what this regular expression is doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
([^=]*)
Make a capturing group of zero or more characters that are not =, grabbing as many as possible until the first equals sign (if one exists).
===
(?:=(.*))?
The second capturing group (.*) grabs everything after the first equals sign, including any additional equals signs. It is wrapped in a non-capturing group (?:...) because we don't want the = part itself to create another capture group.
===
It functions similarly to .split("=") with a limit of one split. A normal .split("=") does not work here because query values can themselves contain equals signs. For example, equation=a=b-2 should become:
["equation", "a=b-2"]
rather than:
["equation", "a", "b-2"]
In Python this is equivalent to:
"equation=a=b-2".split("=", 1)