diff --git a/arrays.js b/arrays.js new file mode 100644 index 0000000..0a47214 --- /dev/null +++ b/arrays.js @@ -0,0 +1,76 @@ +// Complete the following functions. +// These functions only need to work with arrays. +// Do NOT use the built in array methods to solve these. forEach, map, reduce, filter, includes, etc. +// You CAN use concat, push, pop, etc. but do not use the exact method that you are replicating +// You can use the functions that you have already written to help solve the other problems + +const each = (elements, cb) => { + // Iterates over a list of elements, yielding each in turn to the `cb` function. + // This only needs to work with arrays. + // You should also pass the index into `cb` as the second argument + // based off http://underscorejs.org/#each + for (let i = 0; i < elements.length; i++) { + cb(elements[i], i); + } +}; + +const map = (elements, cb) => { + // Produces a new array of values by mapping each value in list through a transformation function (iteratee). + // Return the new array. + const newArray = []; + for (let i = 0; i < elements.length; i++) { + newArray.push(cb(elements[i])); + } + return newArray; +}; + +const reduce = (elements, cb, startingValue) => { + // Combine all elements into a single value going from left to right. + // Elements will be passed one by one into `cb` along with the `startingValue`. + // `startingValue` should be the first argument passed to `cb` and the array element should be the second argument. + // `startingValue` is the starting value. If `startingValue` is undefined then make `elements[0]` the initial value. + let memo = (startingValue === undefined) ? elements[0] : startingValue; + let i = (startingValue === undefined) ? 1 : 0; + for (; i < elements.length; i++) { + memo = cb(memo, elements[i]); + } + return memo; +}; + +const find = (elements, cb) => { + // Look through each value in `elements` and pass each element to `cb`. + // If `cb` returns `true` then return that element. + // Return `undefined` if no elements pass the truth test. + for (let i = 0; i < elements.length; i++) { + if (cb(elements[i])) return elements[i]; + } + return undefined; +}; + +const filter = (elements, cb) => { + // Similar to `find` but you will return an array of all elements that passed the truth test + // Return an empty array if no elements pass the truth test + const newArr = []; + for (let i = 0; i < elements.length; i++) { + if (cb(elements[i])) newArr.push(elements[i]); + } + return newArr; +}; + +/* STRETCH PROBLEM */ + +const flatten = (elements) => { + // Flattens a nested array (the nesting can be to any depth). + // Example: flatten([1, [2], [3, [[4]]]]); => [1, 2, 3, 4]; +}; + +/* eslint-enable no-unused-vars, max-len */ + +module.exports = { + each, + map, + reduce, + find, + filter, + flatten, +}; diff --git a/callbacks.js b/callbacks.js new file mode 100644 index 0000000..0469758 --- /dev/null +++ b/callbacks.js @@ -0,0 +1,65 @@ +/* eslint-disable */ + +const firstItem = (arr, cb) => { + // firstItem passes the first item of the given array to the callback function. + cb(arr[0]); +}; + +const getLength = (arr, cb) => { + // getLength passes the length of the array into the callback. + cb(arr.length); +}; + +const last = (arr, cb) => { + // last passes the last item of the array into the callback. + const arrayLength = arr.length; + cb(arr[arrayLength - 1]); +}; + +const sumNums = (x, y, cb) => { + // sumNums adds two numbers (x, y) and passes the result to the callback. + const sum = x + y; + cb(sum); +}; + +const multiplyNums = (x, y, cb) => { + // multiplyNums multiplies two numbers and passes the result to the callback. + const sum = x * y; + cb(sum); +}; + +const contains = (item, list, cb) => { + // contains checks if an item is present inside of the given array/list. + // Pass true to the callback if it is, otherwise pass false. + for(let i = 0; i < list.length; i++){ + if(item === list[i]) return cb(true); + } + return cb(false); +}; + +/* STRETCH PROBLEM */ + +const removeDuplicates = (array, cb) => { + // removeDuplicates removes all duplicate values from the given array. + // Pass the duplicate free array to the callback function. + // Do not mutate the original array. + const newArr = []; + for(let i = 0; i < array.length; i++){ + contains(array[i], newArr, (isDuplicate) => {if(!isDuplicate) { + newArr.push(array[i]); + } + }) + } + cb(newArr); +}; + +/* eslint-enable */ +module.exports = { + firstItem, + getLength, + last, + sumNums, + multiplyNums, + contains, + removeDuplicates, +}; diff --git a/closure.js b/closure.js new file mode 100644 index 0000000..a176538 --- /dev/null +++ b/closure.js @@ -0,0 +1,58 @@ +// Complete the following functions. + +const counter = () => { + // Return a function that when invoked increments and returns a counter variable. + // Example: const newCounter = counter(); + // newCounter(); // 1 + // newCounter(); // 2 + let tracker = 0; + return () => { return ++tracker; }; +}; + +const counterFactory = () => { + // Return an object that has two methods called `increment` and `decrement`. + // `increment` should increment a counter variable in closure scope and return it. + // `decrement` should decrement the counter variable and return it. + let tracker = 0; + return { + increment: () => { + return ++tracker; + }, + decrement: () => { + return --tracker; + }, + }; +}; + +const limitFunctionCallCount = (cb, n) => { + // Should return a function that invokes `cb`. + // The returned function should only allow `cb` to be invoked `n` times. + let i = 0; + return (...args) => { + if (i < n) { + i++; + return cb(...args); + } + return null; + }; +}; + +/* STRETCH PROBLEM */ + +const cacheFunction = (cb) => { + // Should return a funciton that invokes `cb`. + // A cache (object) should be kept in closure scope. + // The cache should keep track of all arguments have been used to invoke this function. + // If the returned function is invoked with arguments that it has already seen + // then it should return the cached result and not invoke `cb` again. + // `cb` should only ever be invoked once for a given set of arguments. +}; + +/* eslint-enable no-unused-vars */ + +module.exports = { + counter, + counterFactory, + cacheFunction, + limitFunctionCallCount, +}; diff --git a/objects.js b/objects.js new file mode 100644 index 0000000..f4f9cae --- /dev/null +++ b/objects.js @@ -0,0 +1,82 @@ +// Complete the following underscore functions. +// Reference http://underscorejs.org/ for examples. + +const keys = (obj) => { + // Retrieve all the names of the object's properties. + // Return the keys as strings in an array. + // Based on http://underscorejs.org/#keys + const keyArray = []; + Object.keys(obj).forEach((key) => { + keyArray.push(key); + }); + return keyArray; +}; + +const values = (obj) => { + // Return all of the values of the object's own properties. + // Ignore functions + // http://underscorejs.org/#values + return Object.values(obj); +}; + +const mapObject = (obj, cb) => { + // Like map for arrays, but for objects. Transform the value of each property in turn. + // http://underscorejs.org/#mapObject + keys(obj).forEach((key) => { + obj[key] = cb(obj[key]); + }); + return obj; +}; + +const pairs = (obj) => { + // Convert an object into a list of [key, value] pairs. + // http://underscorejs.org/#pairs + const list = []; + keys(obj).forEach((key) => { + const pair = []; + pair.push(key); + pair.push(obj[key]); + list.push(pair); + }); + return list; +}; + +/* STRETCH PROBLEMS */ + +const invert = (obj) => { + // Returns a copy of the object where the keys have become the values and the values the keys. + // Assume that all of the object's values will be unique and string serializable. + // http://underscorejs.org/#invert + const invertedObject = {}; + keys(obj).forEach((key) => { + const keyHolder = key; + const valueHolder = obj[key]; + invertedObject[valueHolder] = keyHolder; + }); + return invertedObject; +}; + +const defaults = (obj, defaultProps) => { + // Fill in undefined properties that match properties on the `defaultProps` parameter object. + // Return `obj`. + // http://underscorejs.org/#defaults + keys(defaultProps).forEach((key) => { + if (obj[key] === undefined) { + keys(defaultProps).forEach((defaultKey) => { + if (defaultKey === key) obj[key] = defaultProps[defaultKey]; + }); + } + }); + return obj; +}; + +/* eslint-enable no-unused-vars */ + +module.exports = { + keys, + values, + mapObject, + pairs, + invert, + defaults, +}; diff --git a/script.js b/script.js new file mode 100644 index 0000000..635625a --- /dev/null +++ b/script.js @@ -0,0 +1 @@ +console.log("Hello world!"); \ No newline at end of file