diff --git a/.results.json b/.results.json new file mode 100644 index 000000000..a6ab8b10b --- /dev/null +++ b/.results.json @@ -0,0 +1,396 @@ +{ + "stats": { + "suites": 11, + "tests": 27, + "passes": 27, + "pending": 0, + "failures": 0, + "start": "2024-08-25T11:54:56.773Z", + "end": "2024-08-25T11:54:57.843Z", + "duration": 1070 + }, + "tests": [ + { + "title": "calls alert with each element passed", + "fullTitle": "index.js myEach calls alert with each element passed", + "duration": 3, + "currentRetry": 0, + "err": {} + }, + { + "title": "calls alert properly on object values", + "fullTitle": "index.js myEach calls alert properly on object values", + "duration": 3, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the original collection", + "fullTitle": "index.js myEach returns the original collection", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "successfully returns a correctly populated array", + "fullTitle": "index.js myMap successfully returns a correctly populated array", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original array", + "fullTitle": "index.js myMap does not modify the original array", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "successfully returns a correctly populated array from modified object values", + "fullTitle": "index.js myMap successfully returns a correctly populated array from modified object values", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myMap does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the correct reduced value when passed an initial value", + "fullTitle": "index.js myReduce returns the correct reduced value when passed an initial value", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the correct reduced value when not passed an initial value", + "fullTitle": "index.js myReduce returns the correct reduced value when not passed an initial value", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original array", + "fullTitle": "index.js myReduce does not modify the original array", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the correct reduced value from object values", + "fullTitle": "index.js myReduce returns the correct reduced value from object values", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myReduce does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the value if found", + "fullTitle": "index.js myFind returns the value if found", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not traverse the whole array if the value is found early", + "fullTitle": "index.js myFind does not traverse the whole array if the value is found early", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns undefined if the value is not present", + "fullTitle": "index.js myFind returns undefined if the value is not present", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly filters for values that the callback evaluates as true", + "fullTitle": "index.js myFilter correctly filters for values that the callback evaluates as true", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly returns an empty array if no matching values are found", + "fullTitle": "index.js myFilter correctly returns an empty array if no matching values are found", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly returns the size of the collection when an array is passed", + "fullTitle": "index.js mySize correctly returns the size of the collection when an array is passed", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly returns the size of the collection (amount of keys) when an object is passed", + "fullTitle": "index.js mySize correctly returns the size of the collection (amount of keys) when an object is passed", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the first element of the collection", + "fullTitle": "index.js myFirst returns the first element of the collection", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the first n elements of the collection when the second optional argument (n) is provided", + "fullTitle": "index.js myFirst returns the first n elements of the collection when the second optional argument (n) is provided", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the last element of the collection", + "fullTitle": "index.js myLast returns the last element of the collection", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the last n elements of the collection when the second optional argument (n) is provided", + "fullTitle": "index.js myLast returns the last n elements of the collection when the second optional argument (n) is provided", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "retrieves all the names of the object's own enumerable properties", + "fullTitle": "index.js myKeys retrieves all the names of the object's own enumerable properties", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myKeys does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "retrieves all the values of the object's own properties", + "fullTitle": "index.js myValues retrieves all the values of the object's own properties", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myValues does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + } + ], + "pending": [], + "failures": [], + "passes": [ + { + "title": "calls alert with each element passed", + "fullTitle": "index.js myEach calls alert with each element passed", + "duration": 3, + "currentRetry": 0, + "err": {} + }, + { + "title": "calls alert properly on object values", + "fullTitle": "index.js myEach calls alert properly on object values", + "duration": 3, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the original collection", + "fullTitle": "index.js myEach returns the original collection", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "successfully returns a correctly populated array", + "fullTitle": "index.js myMap successfully returns a correctly populated array", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original array", + "fullTitle": "index.js myMap does not modify the original array", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "successfully returns a correctly populated array from modified object values", + "fullTitle": "index.js myMap successfully returns a correctly populated array from modified object values", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myMap does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the correct reduced value when passed an initial value", + "fullTitle": "index.js myReduce returns the correct reduced value when passed an initial value", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the correct reduced value when not passed an initial value", + "fullTitle": "index.js myReduce returns the correct reduced value when not passed an initial value", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original array", + "fullTitle": "index.js myReduce does not modify the original array", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the correct reduced value from object values", + "fullTitle": "index.js myReduce returns the correct reduced value from object values", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myReduce does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the value if found", + "fullTitle": "index.js myFind returns the value if found", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not traverse the whole array if the value is found early", + "fullTitle": "index.js myFind does not traverse the whole array if the value is found early", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns undefined if the value is not present", + "fullTitle": "index.js myFind returns undefined if the value is not present", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly filters for values that the callback evaluates as true", + "fullTitle": "index.js myFilter correctly filters for values that the callback evaluates as true", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly returns an empty array if no matching values are found", + "fullTitle": "index.js myFilter correctly returns an empty array if no matching values are found", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly returns the size of the collection when an array is passed", + "fullTitle": "index.js mySize correctly returns the size of the collection when an array is passed", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "correctly returns the size of the collection (amount of keys) when an object is passed", + "fullTitle": "index.js mySize correctly returns the size of the collection (amount of keys) when an object is passed", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the first element of the collection", + "fullTitle": "index.js myFirst returns the first element of the collection", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the first n elements of the collection when the second optional argument (n) is provided", + "fullTitle": "index.js myFirst returns the first n elements of the collection when the second optional argument (n) is provided", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the last element of the collection", + "fullTitle": "index.js myLast returns the last element of the collection", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "returns the last n elements of the collection when the second optional argument (n) is provided", + "fullTitle": "index.js myLast returns the last n elements of the collection when the second optional argument (n) is provided", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "retrieves all the names of the object's own enumerable properties", + "fullTitle": "index.js myKeys retrieves all the names of the object's own enumerable properties", + "duration": 1, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myKeys does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "retrieves all the values of the object's own properties", + "fullTitle": "index.js myValues retrieves all the values of the object's own properties", + "duration": 0, + "currentRetry": 0, + "err": {} + }, + { + "title": "does not modify the original object", + "fullTitle": "index.js myValues does not modify the original object", + "duration": 0, + "currentRetry": 0, + "err": {} + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 31c4e261b..9b5b437d0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,22 @@ # JavaScript Functional Library Project +# JavaScript Functional Library +## Overview + +This library provides functional utilities like `myEach`, `myMap`, and `myReduce`. + +## How to Use + +```javascript +const { myEach, myMap, myReduce } = require('my-functional-library'); + +// Usage example +myEach([1, 2, 3], console.log); +const mapped = myMap([1, 2, 3], num => num * 2); +const reduced = myReduce([1, 2, 3], (acc, val) => acc + val, 0); + +console.log(mapped); // [2, 4, 6] +console.log(reduced); // 6 ## Learning Goals - Gain a greater understanding of JavaScript's built-in collection-processing diff --git a/index.js b/index.js index e69de29bb..156ebb9be 100644 --- a/index.js +++ b/index.js @@ -0,0 +1,169 @@ +// myEach function +function myEach(collection, callback) { + if (Array.isArray(collection)) { + for (let i = 0; i < collection.length; i++) { + callback(collection[i], i, collection); + } + } else { + for (let key in collection) { + if (collection.hasOwnProperty(key)) { + callback(collection[key], key, collection); + } + } + } + return collection; + } + + // myMap function + function myMap(collection, callback) { + const result = []; + myEach(collection, (value, key, collection) => { + result.push(callback(value, key, collection)); + }); + return result; + } + + // myReduce function + function myReduce(collection, callback, acc) { + let start = acc !== undefined ? acc : collection[0]; + + myEach(collection, (value, key, collection) => { + if (acc === undefined && key === 0) return; + start = callback(start, value, collection); + }); + + return start; + } + // myReduce function + function myReduce(collection, callback, acc) { + let keys = Object.keys(collection); + let start = acc !== undefined ? acc : collection[keys[0]]; + myEach(keys, (key, index) => { + if (acc === undefined && index === 0) return; + start = callback(start, collection[key], collection); + }); + + return start; + } + +// myFind.js + +function myFind(collection, callback) { + for (let i = 0; i < collection.length; i++) { + if (callback(collection[i], i, collection)) { + return collection[i]; + } + } + return undefined; +} + +// myFilter.js + +function myFilter(collection, callback) { + const result = []; + + if (Array.isArray(collection)) { + for (let i = 0; i < collection.length; i++) { + if (callback(collection[i], i, collection)) { + result.push(collection[i]); + } + } + } else { + for (let key in collection) { + if (collection.hasOwnProperty(key) && callback(collection[key], key, collection)) { + result.push(collection[key]); + } + } + } + + return result; +} + + +// mySize.js + +function mySize(collection) { + if (Array.isArray(collection)) { + return collection.length; + } else if (typeof collection === 'object') { + return Object.keys(collection).length; + } + return 0; +} + +// myFirst.js + +function myFirst(collection, n = 1) { + if (n === 1) { + return collection[0]; + } else { + return collection.slice(0, n); + } +} +// myLast.js + +function myLast(collection, n = 1) { + if (n === 1) { + return collection[collection.length - 1]; + } else { + return collection.slice(-n); + } +} + +// myFunctions.js + +// Function to retrieve the keys of an object +function myKeys(obj) { + const keys = []; + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + keys.push(key); + } + } + return keys; +} + +// Function to retrieve the values of an object +function myValues(obj) { + const values = []; + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + values.push(obj[key]); + } + } + return values; +} + +// Helper function to compare arrays +function arraysEqual(arrA, arrB) { + if (arrA.length !== arrB.length) return false; + for (let idx = 0; idx < arrA.length; idx++) { + if (Array.isArray(arrA[idx]) && Array.isArray(arrB[idx])) { + if (!arraysEqual(arrA[idx], arrB[idx])) return false; + } else if (arrA[idx] !== arrB[idx]) { + return false; + } + } + return true; +} + +// Helper function to compare objects +function objectsEqual(objA, objB) { + return JSON.stringify(objA) === JSON.stringify(objB); +} + + // Export functions + module.exports = { + myEach, + myMap, + myReduce, + myFind, + myFilter, + mySize, + myFirst, + myLast, + myKeys, + myValues, + arraysEqual, + objectsEqual}; + \ No newline at end of file diff --git a/package.json b/package.json index 81c96dcdb..cebce9c18 100644 --- a/package.json +++ b/package.json @@ -29,11 +29,12 @@ "babel-core": "6.26.3", "babel-preset-env": "1.7.0", "chai": "4.1.2", + "chai-spies-next": "^0.9.3", + "jest": "^29.7.0", "jsdom": "9.2.1", "mocha": "5.2.0", "mocha-jsdom": "~1.1.0", - "mocha-multi": "1.0.1", - "chai-spies-next": "^0.9.3" + "mocha-multi": "1.0.1" }, "dependencies": { "sinon": "^7.3.2"