From dfca4796668c9b4dd13101f6144e7d28915a5926 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:45:02 +0000 Subject: [PATCH 01/24] feat/ add new exercise --- 14_contains/README.md | 3 +++ 14_contains/contains.js | 6 ++++++ 14_contains/contains.spec.js | 15 +++++++++++++++ 14_contains/solution/contains-solution.js | 6 ++++++ 14_contains/solution/contains-solution.spec.js | 15 +++++++++++++++ 5 files changed, 45 insertions(+) create mode 100644 14_contains/README.md create mode 100644 14_contains/contains.js create mode 100644 14_contains/contains.spec.js create mode 100644 14_contains/solution/contains-solution.js create mode 100644 14_contains/solution/contains-solution.spec.js diff --git a/14_contains/README.md b/14_contains/README.md new file mode 100644 index 00000000000..54087cb7376 --- /dev/null +++ b/14_contains/README.md @@ -0,0 +1,3 @@ +# Exercise 13 - contains + +Description of the exercise goes here. diff --git a/14_contains/contains.js b/14_contains/contains.js new file mode 100644 index 00000000000..d5c798c74b7 --- /dev/null +++ b/14_contains/contains.js @@ -0,0 +1,6 @@ +const contains = function() { + +}; + +// Do not edit below this line +module.exports = contains; diff --git a/14_contains/contains.spec.js b/14_contains/contains.spec.js new file mode 100644 index 00000000000..26ecf79b729 --- /dev/null +++ b/14_contains/contains.spec.js @@ -0,0 +1,15 @@ +const contains = require('./contains'); + +describe('contains', () => { + test('First test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(contains()).toBe(''); + }); + + test.skip('Second test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(contains()).toBe(''); + }); +}); diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js new file mode 100644 index 00000000000..6f7201df3c8 --- /dev/null +++ b/14_contains/solution/contains-solution.js @@ -0,0 +1,6 @@ +const contains = function() { + // Replace this comment with the solution code +}; + +// Do not edit below this line +module.exports = contains; diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js new file mode 100644 index 00000000000..97ab46d3796 --- /dev/null +++ b/14_contains/solution/contains-solution.spec.js @@ -0,0 +1,15 @@ +const contains = require('./contains-solution'); + +describe('contains', () => { + test('First test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(contains()).toBe(''); + }); + + test('Second test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(contains()).toBe(''); + }); +}); From 329d7d6d4357f44d879f20169b4a04cabf270520 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 23 Mar 2024 16:25:53 +0000 Subject: [PATCH 02/24] feat/ update README --- 14_contains/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/14_contains/README.md b/14_contains/README.md index 54087cb7376..a42d28dd50d 100644 --- a/14_contains/README.md +++ b/14_contains/README.md @@ -1,3 +1,3 @@ -# Exercise 13 - contains +# Exercise 14 - contains -Description of the exercise goes here. +Write a function that searches for a value in a nested object. It returns true if the object contains that value. From 897b2c167afdbcec7f491ac3f059ebd27b8ee2ed Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 23 Mar 2024 19:21:46 +0000 Subject: [PATCH 03/24] feat/ create tests --- .../solution/contains-solution.spec.js | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 97ab46d3796..2db82584216 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -1,15 +1,45 @@ const contains = require('./contains-solution'); describe('contains', () => { - test('First test description', () => { - // Replace this comment with any other necessary code, and update the expect line as necessary + const nestedObject = { + data: { + banana: NaN, + info: { + magicNumber: 44, + stuff: { + thing: { + banana: NaN, + moreStuff: { + something: 'foo', + answer: [42] + } + } + } + } + } + } - expect(contains()).toBe(''); + test('true if property is number', () => { + expect(contains(nestedObject, 44)).toBe(true); }); - - test('Second test description', () => { - // Replace this comment with any other necessary code, and update the expect line as necessary - expect(contains()).toBe(''); + test('true if property is string', () => { + expect(contains(nestedObject, 'foo')).toBe(true); + }); + + test('does not do type conversions', () => { + expect(contains(nestedObject, '44')).toBe(false); + }); + + test('false if property is not in object', () => { + expect(contains(nestedObject, 'bar')).toBe(false); + }); + + test('true if property is duplicated', () => { + expect(contains(nestedObject, NaN)).toBe(true); + }); + + test('false if property exists but is not primitive', () => { + expect(contains(nestedObject, [42])).toBe(false); }); }); From 59c67684456cebb409f87379c71cd225cbaa4a1e Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 23 Mar 2024 19:22:29 +0000 Subject: [PATCH 04/24] feat/ create solution --- 14_contains/solution/contains-solution.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index 6f7201df3c8..e56cbb65ea0 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,5 +1,11 @@ -const contains = function() { - // Replace this comment with the solution code +const contains = function(current, search) { + if (Object.values(current).includes(search)) return true; + + for (const nestedObject of Object.values(current).filter((value) => typeof value === 'object')) { + return contains(nestedObject, search) + } + + return false }; // Do not edit below this line From ac605aa7daedfb18523e6a2f3b50e39dc479b1b5 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:35:28 +0000 Subject: [PATCH 05/24] feat/ object is not nested --- 14_contains/solution/contains-solution.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 2db82584216..31a8cb43555 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -1,7 +1,7 @@ const contains = require('./contains-solution'); describe('contains', () => { - const nestedObject = { + const object = { data: { banana: NaN, info: { From 7146b0ddd179b1316e3e47c0e613a7e12e0a95fa Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:49:21 +0000 Subject: [PATCH 06/24] feat/ improve wording --- .../solution/contains-solution.spec.js | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 31a8cb43555..aa8fc313b07 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -3,8 +3,9 @@ const contains = require('./contains-solution'); describe('contains', () => { const object = { data: { - banana: NaN, + duplicate: 'e', info: { + duplicate: 'e', magicNumber: 44, stuff: { thing: { @@ -19,27 +20,31 @@ describe('contains', () => { } } - test('true if property is number', () => { - expect(contains(nestedObject, 44)).toBe(true); + test('true if the provided number is a value within the object', () => { + expect(contains(object, 44)).toBe(true); }); - test('true if property is string', () => { - expect(contains(nestedObject, 'foo')).toBe(true); + test('true if the provided string is a value within the object', () => { + expect(contains(object, 'foo')).toBe(true); }); - test('does not do type conversions', () => { - expect(contains(nestedObject, '44')).toBe(false); + test('does not convert input string into a number when searching for a value within the object', () => { + expect(contains(object, '44')).toBe(false); }); - test('false if property is not in object', () => { - expect(contains(nestedObject, 'bar')).toBe(false); + test('false if the provided string is not a value within the object', () => { + expect(contains(object, 'bar')).toBe(false); }); - test('true if property is duplicated', () => { - expect(contains(nestedObject, NaN)).toBe(true); + test('true if the provided string is duplicated', () => { + expect(contains(object, 'e')).toBe(true); }); - test('false if property exists but is not primitive', () => { - expect(contains(nestedObject, [42])).toBe(false); + test('false if the provided property exists but is not a primitive', () => { + expect(contains(object, [42])).toBe(false); + }); + + test('true if NaN is a property within the object', () => { + expect(contains(object, NaN)).toBe(true); }); }); From e4e015d09fc3ac87244e973f43ee0358bb833ed9 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:52:04 +0000 Subject: [PATCH 07/24] feat/ wording --- 14_contains/solution/contains-solution.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index aa8fc313b07..d5619c819f8 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -36,7 +36,7 @@ describe('contains', () => { expect(contains(object, 'bar')).toBe(false); }); - test('true if the provided string is duplicated', () => { + test('true if provided string is within the object, even if duplicated', () => { expect(contains(object, 'e')).toBe(true); }); From 90afe10423e742455cd1026d91f6c94697d1be0e Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:54:07 +0000 Subject: [PATCH 08/24] feat/ wording --- 14_contains/solution/contains-solution.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index d5619c819f8..9a33dedc4c0 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -40,7 +40,7 @@ describe('contains', () => { expect(contains(object, 'e')).toBe(true); }); - test('false if the provided property exists but is not a primitive', () => { + test('false if the provided value exists but is not a primitive', () => { expect(contains(object, [42])).toBe(false); }); From cd0a557215f59cc1d22c1d5f515ee595e4851600 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:55:46 +0000 Subject: [PATCH 09/24] feat/ improve readability of solution Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 14_contains/solution/contains-solution.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index e56cbb65ea0..761ad524ae7 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,11 +1,13 @@ -const contains = function(current, search) { - if (Object.values(current).includes(search)) return true; +const contains = function(obj, searchValue) { + const values = Object.values(obj); + if (values.includes(searchValue)) return true; - for (const nestedObject of Object.values(current).filter((value) => typeof value === 'object')) { - return contains(nestedObject, search) + const nestedObjects = values.filter((value) => typeof value === 'object'); + for (const nestedObject of nestedObjects) { + return contains(nestedObject, searchValue); } - - return false + + return false; }; // Do not edit below this line From 15e4becf9d798516050927ae0665a54770dd0d1b Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 11:31:22 +0000 Subject: [PATCH 10/24] feat/ mention that explicit NaN check is not required --- 14_contains/solution/contains-solution.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index 761ad524ae7..5978f5a424a 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,5 +1,7 @@ const contains = function(obj, searchValue) { const values = Object.values(obj); + + // NaN !== NaN, so we would usually have to do an explicit check to test for it. However, Array.prototype.includes handles that for us if (values.includes(searchValue)) return true; const nestedObjects = values.filter((value) => typeof value === 'object'); From c19c1bc2bf243db001b27ce30b3f9f94b4564cf7 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 12:39:47 +0000 Subject: [PATCH 11/24] feat/ clarify that we would normally use math.isnan --- 14_contains/solution/contains-solution.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index 5978f5a424a..28a6b52345d 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,7 +1,7 @@ const contains = function(obj, searchValue) { const values = Object.values(obj); - // NaN !== NaN, so we would usually have to do an explicit check to test for it. However, Array.prototype.includes handles that for us + // NaN !== NaN, so we would usually have to do an explicit check with Math.isNaN to test for it. However, Array.prototype.includes handles that for us if (values.includes(searchValue)) return true; const nestedObjects = values.filter((value) => typeof value === 'object'); From 4873c5acc50731842edb64586595654d0f5dc99d Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 18:15:29 +0000 Subject: [PATCH 12/24] Update 14_contains/solution/contains-solution.spec.js Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 14_contains/solution/contains-solution.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 9a33dedc4c0..7883abca031 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -44,7 +44,7 @@ describe('contains', () => { expect(contains(object, [42])).toBe(false); }); - test('true if NaN is a property within the object', () => { + test('true if NaN is a value within the object', () => { expect(contains(object, NaN)).toBe(true); }); }); From 360078c88f5a342a2ac5997fbe5d5f0051273539 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 18:24:58 +0000 Subject: [PATCH 13/24] feat/ null check --- 14_contains/solution/contains-solution.js | 2 +- 14_contains/solution/contains-solution.spec.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index 28a6b52345d..fb58c4c8cd6 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -4,7 +4,7 @@ const contains = function(obj, searchValue) { // NaN !== NaN, so we would usually have to do an explicit check with Math.isNaN to test for it. However, Array.prototype.includes handles that for us if (values.includes(searchValue)) return true; - const nestedObjects = values.filter((value) => typeof value === 'object'); + const nestedObjects = values.filter((value) => typeof value === 'object' && value !== null); for (const nestedObject of nestedObjects) { return contains(nestedObject, searchValue); } diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 7883abca031..fb8946638d2 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -7,6 +7,7 @@ describe('contains', () => { info: { duplicate: 'e', magicNumber: 44, + empty: null, stuff: { thing: { banana: NaN, @@ -47,4 +48,8 @@ describe('contains', () => { test('true if NaN is a value within the object', () => { expect(contains(object, NaN)).toBe(true); }); + + test('false if the provided value exists and is null', () => { + expect(contains(object, null)).toBe(true); + }); }); From 8c5851d781bcb695b8e1bd5ae8de28f1a7da192a Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 30 Mar 2024 15:49:59 +0000 Subject: [PATCH 14/24] feat: improve clarity of suggestion Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 14_contains/solution/contains-solution.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index fb58c4c8cd6..a43d76a10a0 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,7 +1,9 @@ const contains = function(obj, searchValue) { const values = Object.values(obj); - // NaN !== NaN, so we would usually have to do an explicit check with Math.isNaN to test for it. However, Array.prototype.includes handles that for us + // NaN === NaN evaluates to false (as per the IEEE 754 standard) + // Normally, we would have to do an explicit Number.isNaN() check to compare NaN equality + // However, Array.prototype.includes automatically handles this for us if (values.includes(searchValue)) return true; const nestedObjects = values.filter((value) => typeof value === 'object' && value !== null); From fc2fc72c1e4680af73fb31b7ead052c4fb4da474 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 30 Mar 2024 16:08:01 +0000 Subject: [PATCH 15/24] feat: remove mention of IEEE --- 14_contains/solution/contains-solution.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index a43d76a10a0..ae8da0b42e8 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,18 +1,20 @@ -const contains = function(obj, searchValue) { +const contains = function (obj, searchValue) { const values = Object.values(obj); - // NaN === NaN evaluates to false (as per the IEEE 754 standard) + // NaN === NaN evaluates to false // Normally, we would have to do an explicit Number.isNaN() check to compare NaN equality // However, Array.prototype.includes automatically handles this for us if (values.includes(searchValue)) return true; - const nestedObjects = values.filter((value) => typeof value === 'object' && value !== null); + const nestedObjects = values.filter( + (value) => typeof value === "object" && value !== null, + ); for (const nestedObject of nestedObjects) { return contains(nestedObject, searchValue); } return false; }; - + // Do not edit below this line module.exports = contains; From 019af1ddcba30af624e8c8779fcfd00b94f43c2f Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 30 Mar 2024 22:01:09 +0000 Subject: [PATCH 16/24] feat: solution now accounts for children nested objects --- 14_contains/solution/contains-solution.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index ae8da0b42e8..65a719cc7ca 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,5 +1,8 @@ -const contains = function (obj, searchValue) { - const values = Object.values(obj); +const contains = function (initialObject, searchValue, queue = []) { + if (initialObject !== null) queue.push(initialObject); + if (initialObject === null && queue.length === 0) return false; + const item = queue.shift(); + const values = Object.values(item); // NaN === NaN evaluates to false // Normally, we would have to do an explicit Number.isNaN() check to compare NaN equality @@ -7,13 +10,13 @@ const contains = function (obj, searchValue) { if (values.includes(searchValue)) return true; const nestedObjects = values.filter( + // typeof null === 'object' evaluates to true ¯\_(ツ)_/¯ (value) => typeof value === "object" && value !== null, ); - for (const nestedObject of nestedObjects) { - return contains(nestedObject, searchValue); - } - return false; + const newQueue = queue.concat(nestedObjects); + + return contains(null, searchValue, newQueue); }; // Do not edit below this line From ee12fc460eff003c6b332e613288bd31228f453c Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sat, 30 Mar 2024 22:02:10 +0000 Subject: [PATCH 17/24] feat: add test to account for children nested objects --- .../solution/contains-solution.spec.js | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index fb8946638d2..917818560bf 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -1,55 +1,55 @@ -const contains = require('./contains-solution'); +const contains = require("./contains-solution"); -describe('contains', () => { +describe("contains", () => { const object = { data: { - duplicate: 'e', + duplicate: "e", + stuff: { + thing: { + banana: NaN, + moreStuff: { + something: "foo", + answer: [42], + }, + }, + }, info: { - duplicate: 'e', - magicNumber: 44, - empty: null, - stuff: { - thing: { - banana: NaN, - moreStuff: { - something: 'foo', - answer: [42] - } - } - } - } - } - } - - test('true if the provided number is a value within the object', () => { + duplicate: "e", + magicNumber: 44, + empty: null, + }, + }, + }; + + test("true if the provided number is a value within the object", () => { expect(contains(object, 44)).toBe(true); }); - test('true if the provided string is a value within the object', () => { - expect(contains(object, 'foo')).toBe(true); + test("true if the provided string is a value within the object", () => { + expect(contains(object, "foo")).toBe(true); }); - test('does not convert input string into a number when searching for a value within the object', () => { - expect(contains(object, '44')).toBe(false); + test("does not convert input string into a number when searching for a value within the object", () => { + expect(contains(object, "44")).toBe(false); }); - test('false if the provided string is not a value within the object', () => { - expect(contains(object, 'bar')).toBe(false); + test("false if the provided string is not a value within the object", () => { + expect(contains(object, "bar")).toBe(false); }); - test('true if provided string is within the object, even if duplicated', () => { - expect(contains(object, 'e')).toBe(true); + test("true if provided string is within the object, even if duplicated", () => { + expect(contains(object, "e")).toBe(true); }); - test('false if the provided value exists but is not a primitive', () => { + test("false if the provided value exists but is not a primitive", () => { expect(contains(object, [42])).toBe(false); }); - test('true if NaN is a value within the object', () => { + test("true if NaN is a value within the object", () => { expect(contains(object, NaN)).toBe(true); }); - test('false if the provided value exists and is null', () => { + test("false if the provided value exists and is null", () => { expect(contains(object, null)).toBe(true); }); }); From cc29bbd8a3836391aec99b1dea11aaadc548cc84 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 7 Apr 2024 01:56:54 +0100 Subject: [PATCH 18/24] feat: use Josh's solution that uses `some` method --- 14_contains/solution/contains-solution.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/14_contains/solution/contains-solution.js b/14_contains/solution/contains-solution.js index 65a719cc7ca..13bf75c1f4b 100644 --- a/14_contains/solution/contains-solution.js +++ b/14_contains/solution/contains-solution.js @@ -1,8 +1,5 @@ -const contains = function (initialObject, searchValue, queue = []) { - if (initialObject !== null) queue.push(initialObject); - if (initialObject === null && queue.length === 0) return false; - const item = queue.shift(); - const values = Object.values(item); +const contains = function (object, searchValue) { + const values = Object.values(object); // NaN === NaN evaluates to false // Normally, we would have to do an explicit Number.isNaN() check to compare NaN equality @@ -11,12 +8,12 @@ const contains = function (initialObject, searchValue, queue = []) { const nestedObjects = values.filter( // typeof null === 'object' evaluates to true ¯\_(ツ)_/¯ - (value) => typeof value === "object" && value !== null, + (value) => typeof value === "object" && value !== null ); - const newQueue = queue.concat(nestedObjects); - - return contains(null, searchValue, newQueue); + return nestedObjects.some((nestedObject) => + contains(nestedObject, searchValue) + ); }; // Do not edit below this line From 0f87177b21d45d4c88ee97c505ae5eb5c23777e0 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:38:19 +0100 Subject: [PATCH 19/24] feat(contains): add some basic examples --- 14_contains/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/14_contains/README.md b/14_contains/README.md index a42d28dd50d..af0d0d0f138 100644 --- a/14_contains/README.md +++ b/14_contains/README.md @@ -1,3 +1,12 @@ # Exercise 14 - contains Write a function that searches for a value in a nested object. It returns true if the object contains that value. + +Objects are compared by reference. + +Examples: + +```javascript +contains({ foo: "foo" }, "bar") // true +contains({ foo: { bar: "bar" } }, "bar") // true +``` From e630a8b19e6730684a634e00d3accbf1f41ccae2 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:43:33 +0100 Subject: [PATCH 20/24] feat(contains): add a more exhaustive test for reference in the object --- 14_contains/solution/contains-solution.spec.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 917818560bf..a73d939667e 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -1,6 +1,7 @@ const contains = require("./contains-solution"); describe("contains", () => { + const meaningOfLifeArray = [42] const object = { data: { duplicate: "e", @@ -9,7 +10,7 @@ describe("contains", () => { banana: NaN, moreStuff: { something: "foo", - answer: [42], + answer: meaningOfLifeArray, }, }, }, @@ -41,10 +42,14 @@ describe("contains", () => { expect(contains(object, "e")).toBe(true); }); - test("false if the provided value exists but is not a primitive", () => { + test("false if the provided array has the same structure as an array within the object, however the reference is not the same", () => { expect(contains(object, [42])).toBe(false); }); + test("true if the provided array is a reference to an array that exists within the object", () => { + expect(contains(object, meaningOfLifeArray)).toBe(true); + }); + test("true if NaN is a value within the object", () => { expect(contains(object, NaN)).toBe(true); }); From 8829ddec244fac997e4ad17a57fde7cb0fd44e2b Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:30:52 +0100 Subject: [PATCH 21/24] feat(contains): move same reference test to the beginning --- 14_contains/solution/contains-solution.spec.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index a73d939667e..7e538262487 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -1,7 +1,7 @@ const contains = require("./contains-solution"); describe("contains", () => { - const meaningOfLifeArray = [42] + const meaningOfLifeArray = [42]; const object = { data: { duplicate: "e", @@ -42,14 +42,14 @@ describe("contains", () => { expect(contains(object, "e")).toBe(true); }); - test("false if the provided array has the same structure as an array within the object, however the reference is not the same", () => { - expect(contains(object, [42])).toBe(false); - }); - test("true if the provided array is a reference to an array that exists within the object", () => { expect(contains(object, meaningOfLifeArray)).toBe(true); }); + test("false if the provided array has the same structure as an array within the object, however the reference is not the same", () => { + expect(contains(object, [42])).toBe(false); + }); + test("true if NaN is a value within the object", () => { expect(contains(object, NaN)).toBe(true); }); From de104e3607e6e5fda63066d2bd10e9a0487eb07e Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:31:49 +0100 Subject: [PATCH 22/24] feat(contains): more concise wording --- 14_contains/solution/contains-solution.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/14_contains/solution/contains-solution.spec.js b/14_contains/solution/contains-solution.spec.js index 7e538262487..36d6496fba4 100644 --- a/14_contains/solution/contains-solution.spec.js +++ b/14_contains/solution/contains-solution.spec.js @@ -42,11 +42,11 @@ describe("contains", () => { expect(contains(object, "e")).toBe(true); }); - test("true if the provided array is a reference to an array that exists within the object", () => { + test("true if the object contains the same object by reference", () => { expect(contains(object, meaningOfLifeArray)).toBe(true); }); - test("false if the provided array has the same structure as an array within the object, however the reference is not the same", () => { + test("false if no matching object reference", () => { expect(contains(object, [42])).toBe(false); }); From a204931e9e3e8f64c646701138832f46cda3ecb1 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:33:10 +0100 Subject: [PATCH 23/24] feat(contains): copy over tests from solution to spec file --- 14_contains/contains.spec.js | 63 ++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/14_contains/contains.spec.js b/14_contains/contains.spec.js index 26ecf79b729..5db2eea33d5 100644 --- a/14_contains/contains.spec.js +++ b/14_contains/contains.spec.js @@ -1,15 +1,60 @@ -const contains = require('./contains'); +const contains = require("./contains"); -describe('contains', () => { - test('First test description', () => { - // Replace this comment with any other necessary code, and update the expect line as necessary +describe("contains", () => { + const meaningOfLifeArray = [42]; + const object = { + data: { + duplicate: "e", + stuff: { + thing: { + banana: NaN, + moreStuff: { + something: "foo", + answer: meaningOfLifeArray, + }, + }, + }, + info: { + duplicate: "e", + magicNumber: 44, + empty: null, + }, + }, + }; - expect(contains()).toBe(''); + test("true if the provided number is a value within the object", () => { + expect(contains(object, 44)).toBe(true); }); - - test.skip('Second test description', () => { - // Replace this comment with any other necessary code, and update the expect line as necessary - expect(contains()).toBe(''); + test.skip("true if the provided string is a value within the object", () => { + expect(contains(object, "foo")).toBe(true); + }); + + test.skip("does not convert input string into a number when searching for a value within the object", () => { + expect(contains(object, "44")).toBe(false); + }); + + test.skip("false if the provided string is not a value within the object", () => { + expect(contains(object, "bar")).toBe(false); + }); + + test.skip("true if provided string is within the object, even if duplicated", () => { + expect(contains(object, "e")).toBe(true); + }); + + test.skip("true if the object contains the same object by reference", () => { + expect(contains(object, meaningOfLifeArray)).toBe(true); + }); + + test.skip("false if no matching object reference", () => { + expect(contains(object, [42])).toBe(false); + }); + + test.skip("true if NaN is a value within the object", () => { + expect(contains(object, NaN)).toBe(true); + }); + + test.skip("false if the provided value exists and is null", () => { + expect(contains(object, null)).toBe(true); }); }); From d1c8f2c818296b4fdd586629874abf202aac0bc0 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:54:34 +0100 Subject: [PATCH 24/24] fix(contains): change false to true for example which is true Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 14_contains/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14_contains/README.md b/14_contains/README.md index af0d0d0f138..d2dab5789f0 100644 --- a/14_contains/README.md +++ b/14_contains/README.md @@ -7,6 +7,6 @@ Objects are compared by reference. Examples: ```javascript -contains({ foo: "foo" }, "bar") // true +contains({ foo: "foo" }, "bar") // false contains({ foo: { bar: "bar" } }, "bar") // true ```