diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..bee1d7889 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,9 +6,18 @@ // or 'list' has mixed values (the function is expected to sort only numbers). function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; - return median; + if (!Array.isArray(list)) return null; + const numbers = list.filter((e) => typeof e === "number" && !isNaN(e)); + + if (numbers.length === 0) return null; + numbers.sort((a, b) => a - b); + const length = numbers.length; + const middleIndex = Math.floor(length / 2); + if (length % 2 === 0) { + return (numbers[middleIndex - 1] + numbers[middleIndex]) / 2; + } else { + return numbers[middleIndex]; + } } module.exports = calculateMedian; diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..786c89e75 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,13 @@ -function dedupe() {} +function dedupe(arr) { + if (arr.length === 0) return []; + const dedupeArray = []; + for (let i = 0; i < arr.length; i++) { + if (!dedupeArray.includes(arr[i])) { + dedupeArray.push(arr[i]); + } + } + + return dedupeArray; +} +console.log(dedupe([1, 1, 2])); +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 23e0f8638..e97e58faa 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -1,4 +1,4 @@ -const dedupe = require("./dedupe.js"); +const dedupe = require("./dedupe"); /* Dedupe Array @@ -16,12 +16,47 @@ E.g. dedupe([1, 2, 1]) target output: [1, 2] // Given an empty array // When passed to the dedupe function // Then it should return an empty array -test.todo("given an empty array, it returns an empty array"); +describe("dedupe()", () => { + [{ input: [], expected: [] }].forEach(({ input, expected }) => + it(`given an empty array, it returns an empty array [${input}]`, () => { + expect(dedupe(input)).not.toBe(expected); + }) + ); + // Given an array with no duplicates + // Then it should return a copy of the original array + [ + { input: [1, 2, 3, 4], expected: [1, 2, 3, 4] }, + { + input: ["apples", "banana", "orange"], + expected: ["apples", "banana", "orange"], + }, + { input: [-1, 7, 1], expected: [-1, 7, 1] }, + ].forEach(({ input, expected }) => + it(`should return same input values [${input}] without duplicate`, () => { + expect(dedupe(input)).toStrictEqual(expected); + }) + ); -// Given an array with no duplicates -// When passed to the dedupe function -// Then it should return a copy of the original array + // When passed to the dedupe function + // Given an array with strings or numbers + // When passed to the dedupe function + // Then it should remove the duplicate values, preserving the first occurence of each element -// Given an array with strings or numbers -// When passed to the dedupe function -// Then it should remove the duplicate values, preserving the first occurence of each element + [ + { input: [1, 2, 5, 5, "a", 5, 10, 10, "a"], expected: [1, 2, 5, "a", 10] }, + { + input: ["apple", "banana", "orange", "apple", "banana", 1, 3, 4, 1], + expected: ["apple", "banana", "orange", 1, 3, 4], + }, + ].forEach(({ input, expected }) => + it(`should return deduplicated array for [${input}]`, () => { + expect(dedupe(input)).toStrictEqual(expected); + }) + ); + + [{ input: [1, 1, 2], expected: [1, 2] }].forEach(({ input, expected }) => + it("returns a copy not the original array", () => { + expect(dedupe(input)).toStrictEqual(expected); + }) + ); +}); diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..30a4e443f 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,20 @@ function findMax(elements) { + if (!Array.isArray(elements)) return "invalid elements"; + const number = []; + for (let i = 0; i < elements.length; i++) { + if (typeof elements[i] === "number" && !Number.isNaN(elements[i])) { + number.push(elements[i]); + } + } + if (number.length === 0) return -Infinity; + let max = number[0]; + + for (let i = 1; i < number.length; i++) { + if (max < number[i]) { + max = number[i]; + } + } + return max; } module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..62617c970 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -16,28 +16,76 @@ const findMax = require("./max.js"); // When passed to the max function // Then it should return -Infinity // Delete this test.todo and replace it with a test. -test.todo("given an empty array, returns -Infinity"); +describe("findMax()", () => { + [{ input: [], expected: -Infinity }].forEach(({ input, expected }) => + it(`should return ${expected} for empty [${input}]`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); -// Given an array with one number -// When passed to the max function -// Then it should return that number + // Given an array with one number + // When passed to the max function + // Then it should return that number -// Given an array with both positive and negative numbers -// When passed to the max function -// Then it should return the largest number overall + [{ input: [50], expected: 50 }].forEach(({ input, expected }) => + it(`should return ${expected} for array [${input}]`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); -// Given an array with just negative numbers -// When passed to the max function -// Then it should return the closest one to zero + // Given an array with both positive and negative numbers + // When passed to the max function + // Then it should return the largest number overall -// Given an array with decimal numbers -// When passed to the max function -// Then it should return the largest decimal number + [{ input: [2, 5, 6, -1, 0, 25, -30], expected: 25 }].forEach( + ({ input, expected }) => { + it(`should return ${expected} for positive and negative numbers in the array`, () => { + expect(findMax(input)).toEqual(expected); + }); + } + ); -// Given an array with non-number values -// When passed to the max function -// Then it should return the max and ignore non-numeric values + // Given an array with just negative numbers + // When passed to the max function + // Then it should return the closest one to zero + [{ input: [-1, -10, -7, -20], expected: -1 }].forEach(({ input, expected }) => + it(`should return negative number nearest to zero`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); -// Given an array with only non-number values -// When passed to the max function -// Then it should return the least surprising value given how it behaves for all other inputs + // Given an array with decimal numbers + // When passed to the max function + // Then it should return the largest decimal number + + [{ input: [0.5, 0.1, 0.56, 0.8, "1.2"], expected: 0.8 }].forEach( + ({ input, expected }) => + it(`should return the largest decimal number from the array`, () => { + expect(findMax(input)).toBeCloseTo(expected); + }) + ); + + // Given an array with non-number values + // When passed to the max function + // Then it should return the max and ignore non-numeric values + [ + { + input: ["edak", "ofonime", "", "@", -4, 10, 6, 50, -100, "300"], + expected: 50, + }, + ].forEach(({ input, expected }) => + it(`should return max numerical value from the array`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); + + // Given an array with only non-number values + // When passed to the max function + // Then it should return the least surprising value given how it behaves for all other inputs + [{ input: ["peter", "", "@", "Hi"], expected: -Infinity }].forEach( + ({ input, expected }) => + it(`should return "invalid elements" for non-numeric values`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); +}); diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..2d2e1050d 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,18 @@ function sum(elements) { + if (!Array.isArray(elements)) return "invalid elements"; + if (elements.length === 0) return 0; + const number = []; + for (const x of elements) { + if (typeof x === "number" && !Number.isNaN(x)) { + number.push(x); + } + } + if (number.length === 0) return "invalid elements"; + let sumOfNum = 0; + for (let i = 0; i < number.length; i++) { + sumOfNum += number[i]; + } + return sumOfNum; } module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..f7be44c77 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -10,27 +10,73 @@ const sum = require("./sum.js"); // Acceptance Criteria: -// Given an empty array -// When passed to the sum function -// Then it should return 0 -test.todo("given an empty array, returns 0") - -// Given an array with just one number -// When passed to the sum function -// Then it should return that number - -// Given an array containing negative numbers -// When passed to the sum function -// Then it should still return the correct total sum - -// Given an array with decimal/float numbers -// When passed to the sum function -// Then it should return the correct total sum - -// Given an array containing non-number values -// When passed to the sum function -// Then it should ignore the non-numerical values and return the sum of the numerical elements - -// Given an array with only non-number values -// When passed to the sum function -// Then it should return the least surprising value given how it behaves for all other inputs +describe("sum()", () => { + // Given an empty array + // When passed to the sum function + // Then it should return 0 + [{ input: [], expected: 0 }].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array with just one number + // When passed to the sum function + // Then it should return that number + + [{ input: [30], expected: 30 }].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array containing negative numbers + // When passed to the sum function + // Then it should still return the correct total sum + + [{ input: [-1, -3, -4, -11], expected: -19 }].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array with decimal/float numbers + // When passed to the sum function + // Then it should return the correct total sum + + [{ input: [0.5, 0.2, 0.11, 0.89, 0.3], expected: 2 }].forEach( + ({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array containing non-number values + // When passed to the sum function + // Then it should ignore the non-numerical values and return the sum of the numerical elements + + [ + { + input: ["evan", 3, "mike", 20, 6, "", "/", undefined, null, 20], + expected: 49, + }, + ].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array with only non-number values + // When passed to the sum function + // Then it should return the least surprising value given how it behaves for all other inputs + [ + { + input: ["evan", "mike", "", "/", undefined], + expected: "invalid elements", + }, + ].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); +}); diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..8c9ae2e66 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,8 +1,7 @@ // Refactor the implementation of includes to use a for...of loop function includes(list, target) { - for (let index = 0; index < list.length; index++) { - const element = list[index]; + for (const element of list) { if (element === target) { return true; }