diff --git a/lab-shannon/.eslintignore b/lab-shannon/.eslintignore new file mode 100644 index 0000000..9ec4b48 --- /dev/null +++ b/lab-shannon/.eslintignore @@ -0,0 +1,7 @@ +# Created by Vinicio Vladimir Sanchez Trejo + +**/node_modules/* +**/vendor/* +**/*.min.js +**/coverage/* +**/build/* diff --git a/lab-shannon/.eslintrc b/lab-shannon/.eslintrc new file mode 100644 index 0000000..3b3fa9d --- /dev/null +++ b/lab-shannon/.eslintrc @@ -0,0 +1,28 @@ +# Created by Vinicio Vladimir Sanchez Trejo + +{ + "env": { + "browser": true, + "node": true, + "commonjs": true, + "jest": true, + "es6": true + }, + "globals": { + "err": true, + "req": true, + "res": true, + "next": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "no-console": "off", + "indent": [ "error", 2 ], + "quotes": ["error", "single", { "allowTemplateLiterals": true }], + "comma-dangle": ["error", "always-multiline"], + "semi": [ "error", "always" ] + } +} diff --git a/lab-shannon/.gitignore b/lab-shannon/.gitignore new file mode 100644 index 0000000..8fe2634 --- /dev/null +++ b/lab-shannon/.gitignore @@ -0,0 +1,148 @@ +# Created by https://www.gitignore.io/api/osx,vim,node,linux,windows,visualstudiocode + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + + +### OSX ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Vim ### +# swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-v][a-z] +[._]sw[a-p] +# session +Session.vim +# temporary +.netrwhist +# auto-generated tag files +tags + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.gitignore.io/api/osx,vim,node,linux,windows,visualstudiocode diff --git a/lab-shannon/README.md b/lab-shannon/README.md new file mode 100644 index 0000000..c243623 --- /dev/null +++ b/lab-shannon/README.md @@ -0,0 +1,9 @@ +The program contains custom .map, .filter, .slice, and .reduce functions. + +.map: The .map function takes two parameters- a callback function and an array of values. It returns a new array containing elements altered from the initial array according to the callback function provided. If the argument provided for the callback is not a function a Type Error is thrown. If one of the elements in the collection is of the wrong type for the callback function provided (i.e. trying to add a string to numbers) a Type Error will be thrown. + +.filter: The .filter function takes two parameters- a callback function and an array of values. It returns a new array containing only the elements which fit the criteria provided in the callback function. If the argument provided for the callback is not a function a Type Error is thrown. + +.slice: The .slice function takes three parameters- a starting position (number), a ending position (number), and an array of data. It returns a new array of elements from the starting point to the ending point (not inclusive) in the collection provided. If one of the elements in the collection is of the wrong type for the callback function provided (i.e. trying to slice a string instead of elements in an array) a Type Error will be thrown. + +.reduce: The .reduce function takes three parameters- a callback function, an array of data, and an initial value. It returns a single value resulting from adding each value in the collection onto the initial value provided. If the argument provided for the callback is not a function a Type Error is thrown. If one of the elements in the collection is of the wrong type for the callback function provided (i.e. trying to add a string to numbers) a Type Error will be thrown. diff --git a/lab-shannon/__test__/fp.test.js b/lab-shannon/__test__/fp.test.js new file mode 100644 index 0000000..6046b0a --- /dev/null +++ b/lab-shannon/__test__/fp.test.js @@ -0,0 +1,87 @@ +'use strict'; + +const fp = require('../lib/fp'); + +describe(`fp.test.js`, () => { + describe(`fp.map function`, () => { + test(`fp.map should return a new array with each element altered based on the callback function`, () => { + expect(fp.map(x => x + 1, [1,2,3])).toEqual([2,3,4]); + expect(fp.map(x => x + 3, [])).toEqual([]); + expect(fp.map(x => x * 2, [1,2,3])).toEqual([2,4,6]); + }); + test(`fp.map should throw a Type Error if the callback provided is not a function`, () => { + expect(() => { + fp.map('I am not a function',[1,2,3]) + }).toThrow(); + }); + test(`fp.map should throw an error if the collection provided is not an array`, () => { + expect(() => { + fp.map(x => x + 1, 'I am not an array') + }).toThrow(); + }) + }) + + describe(`fp.filter`, () => { + test(`fp.filter should return a new array with only the elements which fit the specifications provided`, () => { + expect(fp.filter(num => num > 8, [7,8,9])).toEqual([9]); + expect(fp.filter(string => string.length > 2, ['a', 'hello', 'eh', 'goodbye'])).toEqual(['hello', 'goodbye']); + }); + test(`fp.filter should throw a Type Error if the callback provided is not a function`, () => { + expect(() => { + fp.filter(`I'm not a function`), [1,2,3] + }).toThrow(); + }) + test(`fp.filter should throw an error if the collection provided is not an array`, () => { + expect(() => { + fp.filter(string => string.length < 8, 'I am not an array') + }).toThrow(); + }) + }) + + describe(`fp.slice`, () => { + test(`fp.slice should return a portion of the input from the specified start point to end point (not inclusive`, () => { + expect(fp.slice(0, 4, ['coding', 'is', 'the', 'best', 'ever'])).toEqual(['coding', 'is', 'the', 'best']); + }) + test(`fp.slice should throw an error if the collection provided is not an array`, () => { + expect(() => { + fp.slice(1, 3, 'I am not an array') + }).toThrow(); + }) + test(`fp.slice should throw an error if start is not a positive number`, () => { + expect(() => { + fp.slice(-1, 3, [`do`, `you`, `like`, `coding`]) + }).toThrow(); + }) + test(`fp.slice should throw an error if stop is not a positive number`, () => { + expect(() => { + fp.slice(1, -3, [`do`, `you`, `like`, `coding`]) + }).toThrow(); + }) + }) + + describe(`fp.reduce`, () => { + test(`fp.reduce should return a single value by adding the current element's value in the initial collection onto the starting value provided`, () => { + expect(fp.reduce((accumulator, currentValue) => {return accumulator + currentValue}, [0,1,2,3], 0)).toEqual(6); + }) + test(`fp.reduce should throw a Type Error if the callback provided is not a function`, () => { + expect(() => { + fp.reduce(`I am not a function!`, [1,2,3]) + }).toThrow(); + }) + test(`fp.reduce should throw an error if the collection provided is not an array`, () => { + expect(() => { + fp.reduce((accumulator, currentValue) => {return accumulator + currentValue}, 'I am not an array', 0) + }).toThrow(); + }) + test(`fp.reduce should throw an error if the accumulator's initial value is not a number`, () => { + expect(() => { + fp.reduce((accumulator, currentValue) => {return accumulator + currentValue}, [0,1,2], 'banana') + }).toThrow(); + }) + test(`fp.reduce should throw an error if one of the elements in the collection is not a number`, () => { + expect(() => { + fp.reduce((accumulator, currentValue) => {return accumulator + currentValue}, [1,2,`pie`], 0 + )}).toThrow(); + }) + }) +}); diff --git a/lab-shannon/lib/fp.js b/lab-shannon/lib/fp.js new file mode 100644 index 0000000..bee9406 --- /dev/null +++ b/lab-shannon/lib/fp.js @@ -0,0 +1,58 @@ +'use strict'; + +const fp = module.exports = {}; + +fp.map = (callback, collection) => { + if (typeof callback !== 'function'){ + throw new TypeError('The callback you provided is not a function'); + } + else if (!Array.isArray(collection)){ + throw new TypeError(`The collection provided must be an array`); + } + + return Array.prototype.map.call(collection, callback); +}; + +fp.filter = (callback, collection) => { + if (typeof callback !== 'function'){ + throw new TypeError('The callback you provided is not a function'); + } + else if (!Array.isArray(collection)){ + throw new TypeError(`The collection provided must be an array`); + } + + return Array.prototype.filter.call(collection, callback); +} + +fp.slice = (start, stop, collection) => { + if (!Array.isArray(collection)){ + throw new TypeError(`The collection provided must be an array`); + } + else if (typeof start !== `number` || start < 0){ + throw new Error(`Start must be a positive whole number`) + } + else if (typeof stop !== `number` || stop < 0){ + throw new Error(`Start must be a positive whole number`) + } + + return Array.prototype.slice.call(collection, start, stop); +} + +fp.reduce = (callback, collection, initialValue) => { + if (typeof callback !== 'function'){ + throw new TypeError('The callback you provided is not a function'); + } + else if (!Array.isArray(collection)){ + throw new TypeError(`The collection provided must be an array`); + } + else if (typeof initialValue !== `number`){ + throw new TypeError(`The accumulator must be a number`); + } + else if (!collection.every((num) => { + return typeof num === `number`; + })){ + throw new Error(`All elements of the array must be a number`); + } + + return Array.prototype.reduce.call(collection, callback, initialValue) +} diff --git a/lab-shannon/package.json b/lab-shannon/package.json new file mode 100644 index 0000000..cce91d5 --- /dev/null +++ b/lab-shannon/package.json @@ -0,0 +1,14 @@ +{ + "name": "lab-shannon", + "version": "1.0.0", + "description": "writing stand-alone map, reduce, filter, and slice methods", + "main": "index.js", + "directories": { + "lib": "lib" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "shannon", + "license": "MIT" +}