diff --git a/README.md b/README.md index 65a72b1a0..46fcf2e14 100644 --- a/README.md +++ b/README.md @@ -9,105 +9,103 @@ ## Table of Contents -* [Anagrams of string (with duplicates)](#anagrams-of-string-with-duplicates) +### Array * [Array concatenation](#array-concatenation) * [Array difference](#array-difference) * [Array intersection](#array-intersection) * [Array union](#array-union) * [Average of array of numbers](#average-of-array-of-numbers) -* [Bottom visible](#bottom-visible) -* [Capitalize first letter of every word](#capitalize-first-letter-of-every-word) -* [Capitalize first letter](#capitalize-first-letter) -* [Chain asynchronous functions](#chain-asynchronous-functions) -* [Check for palindrome](#check-for-palindrome) * [Chunk array](#chunk-array) -* [Collatz algorithm](#collatz-algorithm) * [Compact](#compact) * [Count occurrences of a value in array](#count-occurrences-of-a-value-in-array) -* [Current URL](#current-url) -* [Curry](#curry) * [Deep flatten array](#deep-flatten-array) -* [Distance between two points](#distance-between-two-points) -* [Divisible by number](#divisible-by-number) * [Drop elements in array](#drop-elements-in-array) -* [Element is visible in viewport](#element-is-visible-in-viewport) -* [Escape regular expression](#escape-regular-expression) -* [Even or odd number](#even-or-odd-number) -* [Factorial](#factorial) -* [Fibonacci array generator](#fibonacci-array-generator) * [Fill array](#fill-array) * [Filter out non unique values in an array](#filter-out-non-unique-values-in-an-array) * [Flatten array up to depth](#flatten-array-up-to-depth) * [Flatten array](#flatten-array) * [Get max value from array](#get-max-value-from-array) * [Get min value from array](#get-min-value-from-array) -* [Get native type of value](#get-native-type-of-value) -* [Get scroll position](#get-scroll-position) -* [Greatest common divisor (GCD)](#greatest-common-divisor-gcd) * [Group by](#group-by) -* [Hamming distance](#hamming-distance) * [Head of list](#head-of-list) * [Initial of list](#initial-of-list) * [Initialize array with range](#initialize-array-with-range) * [Initialize array with values](#initialize-array-with-values) +* [Last of list](#last-of-list) +* [Median of array of numbers](#median-of-array-of-numbers) +* [Pick](#pick) +* [Shuffle array](#shuffle-array) +* [Similarity between arrays](#similarity-between-arrays) +* [Sum of array of numbers](#sum-of-array-of-numbers) +* [Tail of list](#tail-of-list) +* [Take](#take) +* [Unique values of array](#unique-values-of-array) + +### Browser +* [Bottom visible](#bottom-visible) +* [Current URL](#current-url) +* [Element is visible in viewport](#element-is-visible-in-viewport) +* [Get scroll position](#get-scroll-position) +* [Redirect to URL](#redirect-to-url) +* [Scroll to top](#scroll-to-top) + +### Function +* [Chain asynchronous functions](#chain-asynchronous-functions) +* [Curry](#curry) +* [Pipe](#pipe) +* [Promisify](#promisify) +* [Run promises in series](#run-promises-in-series) +* [Sleep](#sleep) + +### Math +* [Collatz algorithm](#collatz-algorithm) +* [Distance between two points](#distance-between-two-points) +* [Divisible by number](#divisible-by-number) +* [Even or odd number](#even-or-odd-number) +* [Factorial](#factorial) +* [Fibonacci array generator](#fibonacci-array-generator) +* [Greatest common divisor (GCD)](#greatest-common-divisor-gcd) +* [Hamming distance](#hamming-distance) +* [Percentile](#percentile) +* [Powerset](#powerset) +* [Standard deviation](#standard-deviation) + +### Object +* [Object from key value pairs](#object-from-key-value-pairs) +* [Object to key value pairs](#object-to-key-value-pairs) + +### String +* [Anagrams of string (with duplicates)](#anagrams-of-string-with-duplicates) +* [Capitalize first letter of every word](#capitalize-first-letter-of-every-word) +* [Capitalize first letter](#capitalize-first-letter) +* [Check for palindrome](#check-for-palindrome) +* [Reverse a string](#reverse-a-string) +* [Sort characters in string (alphabetical)](#sort-characters-in-string-alphabetical) +* [Truncate a string](#truncate-a-string) + +### Utility +* [Escape regular expression](#escape-regular-expression) +* [Get native type of value](#get-native-type-of-value) * [Is array](#is-array) * [Is boolean](#is-boolean) * [Is function](#is-function) * [Is number](#is-number) * [Is string](#is-string) * [Is symbol](#is-symbol) -* [Last of list](#last-of-list) * [Measure time taken by function](#measure-time-taken-by-function) -* [Median of array of numbers](#median-of-array-of-numbers) -* [Object from key value pairs](#object-from-key-value-pairs) -* [Object to key value pairs](#object-to-key-value-pairs) * [Ordinal suffix of number](#ordinal-suffix-of-number) -* [Percentile](#percentile) -* [Pick](#pick) -* [Pipe](#pipe) -* [Powerset](#powerset) -* [Promisify](#promisify) * [Random integer in range](#random-integer-in-range) * [Random number in range](#random-number-in-range) -* [Redirect to URL](#redirect-to-url) -* [Reverse a string](#reverse-a-string) * [RGB to hexadecimal](#rgb-to-hexadecimal) -* [Run promises in series](#run-promises-in-series) -* [Scroll to top](#scroll-to-top) -* [Shuffle array](#shuffle-array) -* [Similarity between arrays](#similarity-between-arrays) -* [Sleep](#sleep) -* [Sort characters in string (alphabetical)](#sort-characters-in-string-alphabetical) -* [Standard deviation](#standard-deviation) -* [Sum of array of numbers](#sum-of-array-of-numbers) * [Swap values of two variables](#swap-values-of-two-variables) -* [Tail of list](#tail-of-list) -* [Take](#take) -* [Truncate a string](#truncate-a-string) -* [Unique values of array](#unique-values-of-array) * [URL parameters](#url-parameters) * [UUID generator](#uuid-generator) * [Validate email](#validate-email) * [Validate number](#validate-number) * [Value or default](#value-or-default) -### Anagrams of string (with duplicates) +## Array -Use recursion. -For each letter in the given string, create all the partial anagrams for the rest of its letters. -Use `Array.map()` to combine the letter with each partial anagram, then `Array.reduce()` to combine all anagrams in one array. -Base cases are for string `length` equal to `2` or `1`. - -```js -const anagrams = str => { - if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; - return str.split('').reduce((acc, letter, i) => - acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), []); -}; -// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba'] -``` - -[⬆ back to top](#table-of-contents) ### Array concatenation Use `Array.concat()` to concatenate and array with any additional arrays and/or values, specified in `args`. @@ -118,6 +116,7 @@ const arrayConcat = (arr, ...args) => arr.concat(...args); ``` [⬆ back to top](#table-of-contents) + ### Array difference Create a `Set` from `b`, then use `Array.filter()` on `a` to only keep values not contained in `b`. @@ -128,6 +127,7 @@ const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has ``` [⬆ back to top](#table-of-contents) + ### Array intersection Create a `Set` from `b`, then use `Array.filter()` on `a` to only keep values contained in `b`. @@ -138,6 +138,7 @@ const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.ha ``` [⬆ back to top](#table-of-contents) + ### Array union Create a `Set` with all values of `a` and `b` and convert to an array. @@ -148,6 +149,7 @@ const union = (a, b) => Array.from(new Set([...a, ...b])) ``` [⬆ back to top](#table-of-contents) + ### Average of array of numbers Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. @@ -158,69 +160,7 @@ const average = arr => arr.reduce((acc, val) => acc + val, 0) / arr.length; ``` [⬆ back to top](#table-of-contents) -### Bottom visible -Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. - -```js -const bottomVisible = _ => - document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight; -// bottomVisible() -> true -``` - -[⬆ back to top](#table-of-contents) -### Capitalize first letter of every word - -Use `replace()` to match the first character of each word and `toUpperCase()` to capitalize it. - -```js -const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); -// capitalizeEveryWord('hello world!') -> 'Hello World!' -``` - -[⬆ back to top](#table-of-contents) -### Capitalize first letter - -Use `slice(0,1)` and `toUpperCase()` to capitalize first letter, `slice(1)` to get the rest of the string. -Omit the `lowerRest` parameter to keep the rest of the string intact, or set it to `true` to convert to lower case. - -```js -const capitalize = (str, lowerRest = false) => - str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); -// capitalize('myName', true) -> 'Myname' -``` - -[⬆ back to top](#table-of-contents) -### Chain asynchronous functions - -Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed. - -```js -const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); }; -/* -chainAsync([ - next => { console.log('0 seconds'); setTimeout(next, 1000); }, - next => { console.log('1 second'); setTimeout(next, 1000); }, - next => { console.log('2 seconds'); } -]) -*/ -``` - -[⬆ back to top](#table-of-contents) -### Check for palindrome - -Convert string `toLowerCase()` and use `replace()` to remove non-alphanumeric characters from it. -Then, `split('')` into individual characters, `reverse()`, `join('')` and compare to the original, unreversed string, after converting it `tolowerCase()`. - -```js -const palindrome = str => { - const s = str.toLowerCase().replace(/[\W_]/g,''); - return s === s.split('').reverse().join(''); -} -// palindrome('taco cat') -> true - ``` - -[⬆ back to top](#table-of-contents) ### Chunk array Use `Array.from()` to create a new array, that fits the number of chunks that will be produced. @@ -234,17 +174,7 @@ const chunk = (arr, size) => ``` [⬆ back to top](#table-of-contents) -### Collatz algorithm -If `n` is even, return `n/2`. Otherwise return `3n+1`. - -```js -const collatz = n => (n % 2 == 0) ? (n/2) : (3*n+1); -// collatz(8) --> 4 -// collatz(5) --> 16 -``` - -[⬆ back to top](#table-of-contents) ### Compact Use `Array.filter()` to filter out falsey values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`). @@ -255,6 +185,7 @@ const compact = (arr) => arr.filter(v => v); ``` [⬆ back to top](#table-of-contents) + ### Count occurrences of a value in array Use `Array.reduce()` to increment a counter each time you encounter the specific value inside the array. @@ -265,36 +196,7 @@ const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + ``` [⬆ back to top](#table-of-contents) -### Current URL -Use `window.location.href` to get current URL. - -```js -const currentUrl = _ => window.location.href; -// currentUrl() -> 'https://google.com' -``` - -[⬆ back to top](#table-of-contents) -### Curry - -Use recursion. -If the number of provided arguments (`args`) is sufficient, call the passed function `f`. -Otherwise return a curried function `f` that expects the rest of the arguments. -If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. `Math.min()`), you can optionally pass the number of arguments to the second parameter `arity`. - -```js -const curry = (f, arity = f.length, next) => - (next = prevArgs => - nextArg => { - const args = [ ...prevArgs, nextArg ]; - return args.length >= arity ? f(...args) : next(args); - } - )([]); -// curry(Math.pow)(2)(10) -> 1024 -// curry(Math.min, 3)(10)(50)(2) -> 2 -``` - -[⬆ back to top](#table-of-contents) ### Deep flatten array Use recursion. @@ -307,26 +209,7 @@ const deepFlatten = arr => ``` [⬆ back to top](#table-of-contents) -### Distance between two points -Use `Math.hypot()` to calculate the Euclidean distance between two points. - -```js -const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); -// distance(1,1, 2,3) -> 2.23606797749979 -``` - -[⬆ back to top](#table-of-contents) -### Divisible by number - -Use the modulo operator (`%`) to check if the remainder is equal to `0`. - -```js -const isDivisible = (dividend, divisor) => dividend % divisor === 0; -// isDivisible(6,3) -> true -``` - -[⬆ back to top](#table-of-contents) ### Drop elements in array Loop through the array, using `Array.shift()` to drop the first element of the array until the returned value from the function is `true`. @@ -341,6 +224,274 @@ const dropElements = (arr,func) => { ``` [⬆ back to top](#table-of-contents) + +### Fill array + +Use `Array.map()` to map values between `start` (inclusive) and `end` (exclusive) to `value`. +Omit `start` to start at the first element and/or `end` to finish at the last. + +```js +const fillArray = (arr, value, start = 0, end = arr.length) => + arr.map((v,i) => i>=start && i [1,'8','8',4] +``` + +[⬆ back to top](#table-of-contents) + +### Filter out non-unique values in an array + +Use `Array.filter()` for an array containing only the unique values. + +```js +const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); +// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5] +``` + +[⬆ back to top](#table-of-contents) + +### Flatten array up to depth + +Use recursion, decrementing `depth` by 1 for each level of depth. +Use `Array.reduce()` and `Array.concat()` to merge elements or arrays. +Base case, for `depth` equal to `1` stops recursion. +Omit the second element, `depth` to flatten only to a depth of `1` (single flatten). + +```js +const flattenDepth = (arr, depth = 1) => + depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth (v, depth-1) : v), []) + : arr.reduce((a,v) => a.concat(v),[]); +// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5] +``` + +[⬆ back to top](#table-of-contents) + +### Flatten array + +Use `Array.reduce()` to get all elements inside the array and `concat()` to flatten them. + +```js +const flatten = arr => arr.reduce((a, v) => a.concat(v), []); +// flatten([1,[2],3,4]) -> [1,2,3,4] +``` + +[⬆ back to top](#table-of-contents) + +### Get max value from array + +Use `Math.max()` combined with the spread operator (`...`) to get the maximum value in the array. + +```js +const arrayMax = arr => Math.max(...arr); +// arrayMax([10, 1, 5]) -> 10 +``` + +[⬆ back to top](#table-of-contents) + +### Get min value from array + +Use `Math.min()` combined with the spread operator (`...`) to get the minimum value in the array. + +```js +const arrayMin = arr => Math.min(...arr); +// arrayMin([10, 1, 5]) -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Group by + +Use `Array.map()` to map the values of an array to a function or property name. +Use `Array.reduce()` to create an object, where the keys are produced from the mapped results. + +```js +const groupBy = (arr, func) => + arr.map(typeof func === 'function' ? func : val => val[func]) + .reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {}); +// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]} +// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']} +``` + +[⬆ back to top](#table-of-contents) + +### Head of list + +Use `arr[0]` to return the first element of the passed array. + +```js +const head = arr => arr[0]; +// head([1,2,3]) -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Initial of list + +Use `arr.slice(0,-1)`to return all but the last element of the array. + +```js +const initial = arr => arr.slice(0, -1); +// initial([1,2,3]) -> [1,2] +``` + +[⬆ back to top](#table-of-contents) + +### Initialize array with range + +Use `Array(end-start)` to create an array of the desired length, `Array.map()` to fill with the desired values in a range. +You can omit `start` to use a default value of `0`. + +```js +const initializeArrayRange = (end, start = 0) => + Array.apply(null, Array(end - start)).map((v, i) => i + start); +// initializeArrayRange(5) -> [0,1,2,3,4] +``` + +[⬆ back to top](#table-of-contents) + +### Initialize array with values + +Use `Array(n)` to create an array of the desired length, `fill(v)` to fill it with the desired values. +You can omit `value` to use a default value of `0`. + +```js +const initializeArray = (n, value = 0) => Array(n).fill(value); +// initializeArray(5, 2) -> [2,2,2,2,2] +``` + +[⬆ back to top](#table-of-contents) + +### Last of list + +Use `arr.slice(-1)[0]` to get the last element of the given array. + +```js +const last = arr => arr.slice(-1)[0]; +// last([1,2,3]) -> 3 +``` + +[⬆ back to top](#table-of-contents) + +### Median of array of numbers + +Find the middle of the array, use `Array.sort()` to sort the values. +Return the number at the midpoint if `length` is odd, otherwise the average of the two middle numbers. + +```js +const median = arr => { + const mid = Math.floor(arr.length / 2), nums = arr.sort((a, b) => a - b); + return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; +}; +// median([5,6,50,1,-5]) -> 5 +// median([0,10,-2,7]) -> 3.5 +``` + +[⬆ back to top](#table-of-contents) + +### Pick + +Use `Array.reduce()` to convert the filtered/picked keys back to a object with the corresponding key:value pair if the key exist in the obj. + +```js +const pick = (obj, arr) => + arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); +// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 } +// pick(object, ['a', 'c'])['a'] -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Shuffle array + +Use `Array.sort()` to reorder elements, using `Math.random()` in the comparator. + +```js +const shuffle = arr => arr.sort(() => Math.random() - 0.5); +// shuffle([1,2,3]) -> [2,3,1] +``` + +[⬆ back to top](#table-of-contents) + +### Similarity between arrays + +Use `filter()` to remove values that are not part of `values`, determined using `includes()`. + +```js +const similarity = (arr, values) => arr.filter(v => values.includes(v)); +// similarity([1,2,3], [1,2,4]) -> [1,2] +``` + +[⬆ back to top](#table-of-contents) + +### Sum of array of numbers + +Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`. + +```js +const sum = arr => arr.reduce((acc, val) => acc + val, 0); +// sum([1,2,3,4]) -> 10 +``` + +[⬆ back to top](#table-of-contents) + +### Tail of list + +Return `arr.slice(1)` if the array's `length` is more than `1`, otherwise return the whole array. + +```js +const tail = arr => arr.length > 1 ? arr.slice(1) : arr; +// tail([1,2,3]) -> [2,3] +// tail([1]) -> [1] +``` + +[⬆ back to top](#table-of-contents) + +### Take + +Use `Array.slice()` to create a slice of the array with `n` elements taken from the beginning. + +```js +const take = (arr, n = 1) => arr.slice(0, n); +// take([1, 2, 3], 5) -> [1, 2, 3] +// take([1, 2, 3], 0) -> [] +``` + +[⬆ back to top](#table-of-contents) + +### Unique values of array + +Use ES6 `Set` and the `...rest` operator to discard all duplicated values. + +```js +const unique = arr => [...new Set(arr)]; +// unique([1,2,2,3,4,4,5]) -> [1,2,3,4,5] +``` + +[⬆ back to top](#table-of-contents) +## Browser + +### Bottom visible + +Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. + +```js +const bottomVisible = _ => + document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight; +// bottomVisible() -> true +``` + +[⬆ back to top](#table-of-contents) + +### Current URL + +Use `window.location.href` to get current URL. + +```js +const currentUrl = _ => window.location.href; +// currentUrl() -> 'https://google.com' +``` + +[⬆ back to top](#table-of-contents) + ### Element is visible in viewport Use `Element.getBoundingClientRect()` and the `window.inner(Width|Height)` values @@ -362,129 +513,7 @@ const elementIsVisibleInViewport = (el, partiallyVisible = false) => { ``` [⬆ back to top](#table-of-contents) -### Escape regular expression -Use `replace()` to escape special characters. - -```js -const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -// escapeRegExp('(test)') -> \\(test\\) -``` - -[⬆ back to top](#table-of-contents) -### Even or odd number - -Checks whether a number is odd or even using the modulo (`%`) operator. -Returns `true` if the number is even, `false` if the number is odd. - -```js -const isEven = num => num % 2 === 0; -// isEven(3) -> false -``` - -[⬆ back to top](#table-of-contents) -### Factorial - -Use recursion. -If `n` is less than or equal to `1`, return `1`. -Otherwise, return the product of `n` and the factorial of `n - 1`. - -```js -const factorial = n => n <= 1 ? 1 : n * factorial(n - 1); -// factorial(6) -> 720 -``` - -[⬆ back to top](#table-of-contents) -### Fibonacci array generator - -Create an empty array of the specific length, initializing the first two values (`0` and `1`). -Use `Array.reduce()` to add values into the array, using the sum of the last two values, except for the first two. - -```js -const fibonacci = n => - Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); -// fibonacci(5) -> [0,1,1,2,3] -``` - -[⬆ back to top](#table-of-contents) -### Fill array - -Use `Array.map()` to map values between `start` (inclusive) and `end` (exclusive) to `value`. -Omit `start` to start at the first element and/or `end` to finish at the last. - -```js -const fillArray = (arr, value, start = 0, end = arr.length) => - arr.map((v,i) => i>=start && i [1,'8','8',4] -``` - -[⬆ back to top](#table-of-contents) -### Filter out non-unique values in an array - -Use `Array.filter()` for an array containing only the unique values. - -```js -const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); -// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5] -``` - -[⬆ back to top](#table-of-contents) -### Flatten array up to depth - -Use recursion, decrementing `depth` by 1 for each level of depth. -Use `Array.reduce()` and `Array.concat()` to merge elements or arrays. -Base case, for `depth` equal to `1` stops recursion. -Omit the second element, `depth` to flatten only to a depth of `1` (single flatten). - -```js -const flattenDepth = (arr, depth = 1) => - depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth (v, depth-1) : v), []) - : arr.reduce((a,v) => a.concat(v),[]); -// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5] -``` - -[⬆ back to top](#table-of-contents) -### Flatten array - -Use `Array.reduce()` to get all elements inside the array and `concat()` to flatten them. - -```js -const flatten = arr => arr.reduce((a, v) => a.concat(v), []); -// flatten([1,[2],3,4]) -> [1,2,3,4] -``` - -[⬆ back to top](#table-of-contents) -### Get max value from array - -Use `Math.max()` combined with the spread operator (`...`) to get the maximum value in the array. - -```js -const arrayMax = arr => Math.max(...arr); -// arrayMax([10, 1, 5]) -> 10 -``` - -[⬆ back to top](#table-of-contents) -### Get min value from array - -Use `Math.min()` combined with the spread operator (`...`) to get the minimum value in the array. - -```js -const arrayMin = arr => Math.min(...arr); -// arrayMin([10, 1, 5]) -> 1 -``` - -[⬆ back to top](#table-of-contents) -### Get native type of value - -Returns lower-cased constructor name of value, "undefined" or "null" if value is undefined or null - -```js -const getType = v => - v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); -// getType(new Set([1,2,3])) -> "set" -``` - -[⬆ back to top](#table-of-contents) ### Get scroll position Use `pageXOffset` and `pageYOffset` if they are defined, otherwise `scrollLeft` and `scrollTop`. @@ -498,254 +527,67 @@ const getScrollPos = (el = window) => ``` [⬆ back to top](#table-of-contents) -### Greatest common divisor (GCD) + +undefined +[⬆ back to top](#table-of-contents) + +### Scroll to top + +Get distance from top using `document.documentElement.scrollTop` or `document.body.scrollTop`. +Scroll by a fraction of the distance from top. Use `window.requestAnimationFrame()` to animate the scrolling. + +```js +const scrollToTop = _ => { + const c = document.documentElement.scrollTop || document.body.scrollTop; + if (c > 0) { + window.requestAnimationFrame(scrollToTop); + window.scrollTo(0, c - c / 8); + } +}; +// scrollToTop() +``` + +[⬆ back to top](#table-of-contents) +## Function + +### Chain asynchronous functions + +Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed. + +```js +const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); }; +/* +chainAsync([ + next => { console.log('0 seconds'); setTimeout(next, 1000); }, + next => { console.log('1 second'); setTimeout(next, 1000); }, + next => { console.log('2 seconds'); } +]) +*/ +``` + +[⬆ back to top](#table-of-contents) + +### Curry Use recursion. -Base case is when `y` equals `0`. In this case, return `x`. -Otherwise, return the GCD of `y` and the remainder of the division `x/y`. +If the number of provided arguments (`args`) is sufficient, call the passed function `f`. +Otherwise return a curried function `f` that expects the rest of the arguments. +If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. `Math.min()`), you can optionally pass the number of arguments to the second parameter `arity`. ```js -const gcd = (x, y) => !y ? x : gcd(y, x % y); -// gcd (8, 36) -> 4 +const curry = (f, arity = f.length, next) => + (next = prevArgs => + nextArg => { + const args = [ ...prevArgs, nextArg ]; + return args.length >= arity ? f(...args) : next(args); + } + )([]); +// curry(Math.pow)(2)(10) -> 1024 +// curry(Math.min, 3)(10)(50)(2) -> 2 ``` [⬆ back to top](#table-of-contents) -### Group by -Use `Array.map()` to map the values of an array to a function or property name. -Use `Array.reduce()` to create an object, where the keys are produced from the mapped results. - -```js -const groupBy = (arr, func) => - arr.map(typeof func === 'function' ? func : val => val[func]) - .reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {}); -// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]} -// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']} -``` - -[⬆ back to top](#table-of-contents) -### Hamming distance - -Use XOR operator (`^`) to find the bit difference between the two numbers, convert to binary string using `toString(2)`. -Count and return the number of `1`s in the string, using `match(/1/g)`. - -```js -const hammingDistance = (num1, num2) => - ((num1 ^ num2).toString(2).match(/1/g) || '').length; -// hammingDistance(2,3) -> 1 -``` - -[⬆ back to top](#table-of-contents) -### Head of list - -Use `arr[0]` to return the first element of the passed array. - -```js -const head = arr => arr[0]; -// head([1,2,3]) -> 1 -``` - -[⬆ back to top](#table-of-contents) -### Initial of list - -Use `arr.slice(0,-1)`to return all but the last element of the array. - -```js -const initial = arr => arr.slice(0, -1); -// initial([1,2,3]) -> [1,2] -``` - -[⬆ back to top](#table-of-contents) -### Initialize array with range - -Use `Array(end-start)` to create an array of the desired length, `Array.map()` to fill with the desired values in a range. -You can omit `start` to use a default value of `0`. - -```js -const initializeArrayRange = (end, start = 0) => - Array.apply(null, Array(end - start)).map((v, i) => i + start); -// initializeArrayRange(5) -> [0,1,2,3,4] -``` - -[⬆ back to top](#table-of-contents) -### Initialize array with values - -Use `Array(n)` to create an array of the desired length, `fill(v)` to fill it with the desired values. -You can omit `value` to use a default value of `0`. - -```js -const initializeArray = (n, value = 0) => Array(n).fill(value); -// initializeArray(5, 2) -> [2,2,2,2,2] -``` - -[⬆ back to top](#table-of-contents) -### Is array - -Use `Array.isArray()` to check if a value is classified as an array. - -```js -const isArray = val => val && Array.isArray(val); -// isArray(null) -> false -// isArray([1]) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is boolean - -Use `typeof` to check if a value is classified as a boolean primitive. - -```js -const isBoolean = val => typeof val === 'boolean'; -// isBoolean(null) -> false -// isBoolean(false) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is function - -Use `typeof` to check if a value is classified as a function primitive. - -```js -const isFunction = val => val && typeof val === 'function'; -// isFunction('x') -> false -// isFunction(x => x) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is number - -Use `typeof` to check if a value is classified as a number primitive. - -```js -const isNumber = val => typeof val === 'number'; -// isNumber('1') -> false -// isNumber(1) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is string - -Use `typeof` to check if a value is classified as a string primitive. - -```js -const isString = val => typeof val === 'string'; -// isString(10) -> false -// isString('10') -> true -``` - -[⬆ back to top](#table-of-contents) -### Is symbol - -Use `typeof` to check if a value is classified as a symbol primitive. - -```js -const isSymbol = val => typeof val === 'symbol'; -// isSymbol('x') -> false -// isSymbol(Symbol('x')) -> true -``` - -[⬆ back to top](#table-of-contents) -### Last of list - -Use `arr.slice(-1)[0]` to get the last element of the given array. - -```js -const last = arr => arr.slice(-1)[0]; -// last([1,2,3]) -> 3 -``` - -[⬆ back to top](#table-of-contents) -### Measure time taken by function - -Use `performance.now()` to get start and end time for the function, `console.log()` the time taken. -Pass a callback function as the argument. - -```js -const timeTaken = callback => { - const t0 = performance.now(), r = callback(); - console.log(performance.now() - t0); - return r; -}; -// timeTaken(() => Math.pow(2, 10)) -> 1024 (0.010000000009313226 logged in console) -``` - -[⬆ back to top](#table-of-contents) -### Median of array of numbers - -Find the middle of the array, use `Array.sort()` to sort the values. -Return the number at the midpoint if `length` is odd, otherwise the average of the two middle numbers. - -```js -const median = arr => { - const mid = Math.floor(arr.length / 2), nums = arr.sort((a, b) => a - b); - return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; -}; -// median([5,6,50,1,-5]) -> 5 -// median([0,10,-2,7]) -> 3.5 -``` - -[⬆ back to top](#table-of-contents) -### Object from key-value pairs - -Use `Array.reduce()` to create and combine key-value pairs. - -```js -const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); -// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2} -``` - -[⬆ back to top](#table-of-contents) -### Object to key-value pairs - -Use `Object.keys()` and `Array.map()` to iterate over the object's keys and produce an array with key-value pairs. - -```js -const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); -// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]]) -``` - -[⬆ back to top](#table-of-contents) -### Ordinal suffix of number - -Use the modulo operator (`%`) to find values of single and tens digits. -Find which ordinal pattern digits match. -If digit is found in teens pattern, use teens ordinal. - -```js -const toOrdinalSuffix = num => { - const int = parseInt(num), digits = [(int % 10), (int % 100)], - ordinals = ["st", "nd", "rd", "th"], oPattern = [1,2,3,4], - tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19] - return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0]-1] : int + ordinals[3]; -} -// toOrdinalSuffix("123") -> "123rd" -``` - -[⬆ back to top](#table-of-contents) -### Percentile - -Use `Array.reduce()` to calculate how many numbers are below the value and how many are the same value and -apply the percentile formula. - -```js -const percentile = (arr, val) => - 100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length; -// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55 - ``` - -[⬆ back to top](#table-of-contents) -### Pick - -Use `Array.reduce()` to convert the filtered/picked keys back to a object with the corresponding key:value pair if the key exist in the obj. - -```js -const pick = (obj, arr) => - arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); -// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 } -// pick(object, ['a', 'c'])['a'] -> 1 -``` - -[⬆ back to top](#table-of-contents) ### Pipe Use `Array.reduce()` to pass value through functions. @@ -756,17 +598,7 @@ const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg); ``` [⬆ back to top](#table-of-contents) -### Powerset -Use `Array.reduce()` combined with `Array.map()` to iterate over elements and combine into an array containing all combinations. - -```js -const powerset = arr => - arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); -// powerset([1,2]) -> [[], [1], [2], [2,1]] -``` - -[⬆ back to top](#table-of-contents) ### Promisify Use currying to return a function returning a `Promise` that calls the original function. @@ -786,59 +618,7 @@ const promisify = func => ``` [⬆ back to top](#table-of-contents) -### Random integer in range -Use `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. - -```js -const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; -// randomIntegerInRange(0, 5) -> 2 -``` - -[⬆ back to top](#table-of-contents) -### Random number in range - -Use `Math.random()` to generate a random value, map it to the desired range using multiplication. - -```js -const randomInRange = (min, max) => Math.random() * (max - min) + min; -// randomInRange(2,10) -> 6.0211363285087005 -``` - -[⬆ back to top](#table-of-contents) -### Redirect to URL - -Use `window.location.href` or `window.location.replace()` to redirect to `url`. -Pass a second argument to simulate a link click (`true` - default) or an HTTP redirect (`false`). - -```js -const redirect = (url, asLink = true) => - asLink ? window.location.href = url : window.location.replace(url); -// redirect('https://google.com') -``` - -[⬆ back to top](#table-of-contents) -### Reverse a string - -Use array destructuring and `Array.reverse()` to reverse the order of the characters in the string. -Combine characters to get a string using `join('')`. - -```js -const reverseString = str => [...str].reverse().join(''); -// reverseString('foobar') -> 'raboof' -``` - -[⬆ back to top](#table-of-contents) -### RGB to hexadecimal - -Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (`<<`) and `toString(16)`, then `padStart(6,'0')` to get a 6-digit hexadecimal value. - -```js -const rgbToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); -// rgbToHex(255, 165, 1) -> 'ffa501' -``` - -[⬆ back to top](#table-of-contents) ### Run promises in series Run an array of promises in series using `Array.reduce()` by creating a promise chain, where each promise returns the next promise when resolved. @@ -850,43 +630,7 @@ const series = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); ``` [⬆ back to top](#table-of-contents) -### Scroll to top -Get distance from top using `document.documentElement.scrollTop` or `document.body.scrollTop`. -Scroll by a fraction of the distance from top. Use `window.requestAnimationFrame()` to animate the scrolling. - -```js -const scrollToTop = _ => { - const c = document.documentElement.scrollTop || document.body.scrollTop; - if (c > 0) { - window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c / 8); - } -}; -// scrollToTop() -``` - -[⬆ back to top](#table-of-contents) -### Shuffle array - -Use `Array.sort()` to reorder elements, using `Math.random()` in the comparator. - -```js -const shuffle = arr => arr.sort(() => Math.random() - 0.5); -// shuffle([1,2,3]) -> [2,3,1] -``` - -[⬆ back to top](#table-of-contents) -### Similarity between arrays - -Use `filter()` to remove values that are not part of `values`, determined using `includes()`. - -```js -const similarity = (arr, values) => arr.filter(v => values.includes(v)); -// similarity([1,2,3], [1,2,4]) -> [1,2] -``` - -[⬆ back to top](#table-of-contents) ### Sleep Delay executing part of an `async` function, by putting it to sleep, returning a `Promise`. @@ -903,17 +647,131 @@ async function sleepyWork() { ``` [⬆ back to top](#table-of-contents) -### Sort characters in string (alphabetical) +## Math -Split the string using `split('')`, `Array.sort()` utilizing `localeCompare()`, recombine using `join('')`. +### Collatz algorithm + +If `n` is even, return `n/2`. Otherwise return `3n+1`. ```js -const sortCharactersInString = str => - str.split('').sort((a, b) => a.localeCompare(b)).join(''); -// sortCharactersInString('cabbage') -> 'aabbceg' +const collatz = n => (n % 2 == 0) ? (n/2) : (3*n+1); +// collatz(8) --> 4 +// collatz(5) --> 16 ``` [⬆ back to top](#table-of-contents) + +### Distance between two points + +Use `Math.hypot()` to calculate the Euclidean distance between two points. + +```js +const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); +// distance(1,1, 2,3) -> 2.23606797749979 +``` + +[⬆ back to top](#table-of-contents) + +### Divisible by number + +Use the modulo operator (`%`) to check if the remainder is equal to `0`. + +```js +const isDivisible = (dividend, divisor) => dividend % divisor === 0; +// isDivisible(6,3) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Even or odd number + +Checks whether a number is odd or even using the modulo (`%`) operator. +Returns `true` if the number is even, `false` if the number is odd. + +```js +const isEven = num => num % 2 === 0; +// isEven(3) -> false +``` + +[⬆ back to top](#table-of-contents) + +### Factorial + +Use recursion. +If `n` is less than or equal to `1`, return `1`. +Otherwise, return the product of `n` and the factorial of `n - 1`. + +```js +const factorial = n => n <= 1 ? 1 : n * factorial(n - 1); +// factorial(6) -> 720 +``` + +[⬆ back to top](#table-of-contents) + +### Fibonacci array generator + +Create an empty array of the specific length, initializing the first two values (`0` and `1`). +Use `Array.reduce()` to add values into the array, using the sum of the last two values, except for the first two. + +```js +const fibonacci = n => + Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); +// fibonacci(5) -> [0,1,1,2,3] +``` + +[⬆ back to top](#table-of-contents) + +### Greatest common divisor (GCD) + +Use recursion. +Base case is when `y` equals `0`. In this case, return `x`. +Otherwise, return the GCD of `y` and the remainder of the division `x/y`. + +```js +const gcd = (x, y) => !y ? x : gcd(y, x % y); +// gcd (8, 36) -> 4 +``` + +[⬆ back to top](#table-of-contents) + +### Hamming distance + +Use XOR operator (`^`) to find the bit difference between the two numbers, convert to binary string using `toString(2)`. +Count and return the number of `1`s in the string, using `match(/1/g)`. + +```js +const hammingDistance = (num1, num2) => + ((num1 ^ num2).toString(2).match(/1/g) || '').length; +// hammingDistance(2,3) -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Percentile + +Use `Array.reduce()` to calculate how many numbers are below the value and how many are the same value and +apply the percentile formula. + +```js +const percentile = (arr, val) => + 100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length; +// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55 + ``` + +[⬆ back to top](#table-of-contents) + +### Powerset + +Use `Array.reduce()` combined with `Array.map()` to iterate over elements and combine into an array containing all combinations. + +```js +const powerset = arr => + arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); +// powerset([1,2]) -> [[], [1], [2], [2,1]] +``` + +[⬆ back to top](#table-of-contents) + ### Standard deviation Use `Array.reduce()` to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then @@ -933,49 +791,112 @@ const standardDeviation = (arr, usePopulation = false) => { ``` [⬆ back to top](#table-of-contents) -### Sum of array of numbers +## Object -Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`. +### Object from key-value pairs + +Use `Array.reduce()` to create and combine key-value pairs. ```js -const sum = arr => arr.reduce((acc, val) => acc + val, 0); -// sum([1,2,3,4]) -> 10 +const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); +// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2} ``` [⬆ back to top](#table-of-contents) -### Swap values of two variables -Use array destructuring to swap values between two variables. +### Object to key-value pairs + +Use `Object.keys()` and `Array.map()` to iterate over the object's keys and produce an array with key-value pairs. ```js -[varA, varB] = [varB, varA]; -// [x, y] = [y, x] +const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); +// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]]) ``` [⬆ back to top](#table-of-contents) -### Tail of list +## String -Return `arr.slice(1)` if the array's `length` is more than `1`, otherwise return the whole array. +### Anagrams of string (with duplicates) + +Use recursion. +For each letter in the given string, create all the partial anagrams for the rest of its letters. +Use `Array.map()` to combine the letter with each partial anagram, then `Array.reduce()` to combine all anagrams in one array. +Base cases are for string `length` equal to `2` or `1`. ```js -const tail = arr => arr.length > 1 ? arr.slice(1) : arr; -// tail([1,2,3]) -> [2,3] -// tail([1]) -> [1] +const anagrams = str => { + if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; + return str.split('').reduce((acc, letter, i) => + acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), []); +}; +// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba'] ``` [⬆ back to top](#table-of-contents) -### Take -Use `Array.slice()` to create a slice of the array with `n` elements taken from the beginning. +### Capitalize first letter of every word + +Use `replace()` to match the first character of each word and `toUpperCase()` to capitalize it. ```js -const take = (arr, n = 1) => arr.slice(0, n); - -// take([1, 2, 3], 5) -> [1, 2, 3] -// take([1, 2, 3], 0) -> [] +const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); +// capitalizeEveryWord('hello world!') -> 'Hello World!' ``` [⬆ back to top](#table-of-contents) + +### Capitalize first letter + +Use `slice(0,1)` and `toUpperCase()` to capitalize first letter, `slice(1)` to get the rest of the string. +Omit the `lowerRest` parameter to keep the rest of the string intact, or set it to `true` to convert to lower case. + +```js +const capitalize = (str, lowerRest = false) => + str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); +// capitalize('myName', true) -> 'Myname' +``` + +[⬆ back to top](#table-of-contents) + +### Check for palindrome + +Convert string `toLowerCase()` and use `replace()` to remove non-alphanumeric characters from it. +Then, `split('')` into individual characters, `reverse()`, `join('')` and compare to the original, unreversed string, after converting it `tolowerCase()`. + +```js +const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g,''); + return s === s.split('').reverse().join(''); +} +// palindrome('taco cat') -> true + ``` + +[⬆ back to top](#table-of-contents) + +### Reverse a string + +Use array destructuring and `Array.reverse()` to reverse the order of the characters in the string. +Combine characters to get a string using `join('')`. + +```js +const reverseString = str => [...str].reverse().join(''); +// reverseString('foobar') -> 'raboof' +``` + +[⬆ back to top](#table-of-contents) + +### Sort characters in string (alphabetical) + +Split the string using `split('')`, `Array.sort()` utilizing `localeCompare()`, recombine using `join('')`. + +```js +const sortCharactersInString = str => + str.split('').sort((a, b) => a.localeCompare(b)).join(''); +// sortCharactersInString('cabbage') -> 'aabbceg' +``` + +[⬆ back to top](#table-of-contents) + ### Truncate a String Determine if the string's `length` is greater than `num`. @@ -988,16 +909,181 @@ const truncate = (str, num) => ``` [⬆ back to top](#table-of-contents) -### Unique values of array +## Utility -Use ES6 `Set` and the `...rest` operator to discard all duplicated values. +### Escape regular expression + +Use `replace()` to escape special characters. ```js -const unique = arr => [...new Set(arr)]; -// unique([1,2,2,3,4,4,5]) -> [1,2,3,4,5] +const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +// escapeRegExp('(test)') -> \\(test\\) ``` [⬆ back to top](#table-of-contents) + +### Get native type of value + +Returns lower-cased constructor name of value, "undefined" or "null" if value is undefined or null + +```js +const getType = v => + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); +// getType(new Set([1,2,3])) -> "set" +``` + +[⬆ back to top](#table-of-contents) + +### Is array + +Use `Array.isArray()` to check if a value is classified as an array. + +```js +const isArray = val => val && Array.isArray(val); +// isArray(null) -> false +// isArray([1]) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is boolean + +Use `typeof` to check if a value is classified as a boolean primitive. + +```js +const isBoolean = val => typeof val === 'boolean'; +// isBoolean(null) -> false +// isBoolean(false) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is function + +Use `typeof` to check if a value is classified as a function primitive. + +```js +const isFunction = val => val && typeof val === 'function'; +// isFunction('x') -> false +// isFunction(x => x) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is number + +Use `typeof` to check if a value is classified as a number primitive. + +```js +const isNumber = val => typeof val === 'number'; +// isNumber('1') -> false +// isNumber(1) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is string + +Use `typeof` to check if a value is classified as a string primitive. + +```js +const isString = val => typeof val === 'string'; +// isString(10) -> false +// isString('10') -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is symbol + +Use `typeof` to check if a value is classified as a symbol primitive. + +```js +const isSymbol = val => typeof val === 'symbol'; +// isSymbol('x') -> false +// isSymbol(Symbol('x')) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Measure time taken by function + +Use `performance.now()` to get start and end time for the function, `console.log()` the time taken. +Pass a callback function as the argument. + +```js +const timeTaken = callback => { + const t0 = performance.now(), r = callback(); + console.log(performance.now() - t0); + return r; +}; +// timeTaken(() => Math.pow(2, 10)) -> 1024 (0.010000000009313226 logged in console) +``` + +[⬆ back to top](#table-of-contents) + +### Ordinal suffix of number + +Use the modulo operator (`%`) to find values of single and tens digits. +Find which ordinal pattern digits match. +If digit is found in teens pattern, use teens ordinal. + +```js +const toOrdinalSuffix = num => { + const int = parseInt(num), digits = [(int % 10), (int % 100)], + ordinals = ["st", "nd", "rd", "th"], oPattern = [1,2,3,4], + tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19] + return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0]-1] : int + ordinals[3]; +} +// toOrdinalSuffix("123") -> "123rd" +``` + +[⬆ back to top](#table-of-contents) + +### Random integer in range + +Use `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. + +```js +const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; +// randomIntegerInRange(0, 5) -> 2 +``` + +[⬆ back to top](#table-of-contents) + +### Random number in range + +Use `Math.random()` to generate a random value, map it to the desired range using multiplication. + +```js +const randomInRange = (min, max) => Math.random() * (max - min) + min; +// randomInRange(2,10) -> 6.0211363285087005 +``` + +[⬆ back to top](#table-of-contents) + +### RGB to hexadecimal + +Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (`<<`) and `toString(16)`, then `padStart(6,'0')` to get a 6-digit hexadecimal value. + +```js +const rgbToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); +// rgbToHex(255, 165, 1) -> 'ffa501' +``` + +[⬆ back to top](#table-of-contents) + +### Swap values of two variables + +Use array destructuring to swap values between two variables. + +```js +[varA, varB] = [varB, varA]; +// [x, y] = [y, x] +``` + +[⬆ back to top](#table-of-contents) + ### URL parameters Use `match()` with an appropriate regular expression to get all key-value pairs, `Array.reduce()` to map and combine them into a single object. @@ -1012,6 +1098,7 @@ const getUrlParameters = url => ``` [⬆ back to top](#table-of-contents) + ### UUID generator Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4. @@ -1025,6 +1112,7 @@ const uuid = _ => ``` [⬆ back to top](#table-of-contents) + ### Validate email Use a regular experssion to check if the email is valid. @@ -1037,6 +1125,7 @@ const validateEmail = str => ``` [⬆ back to top](#table-of-contents) + ### Validate number Use `!isNaN` in combination with `parseFloat()` to check if the argument is a number. @@ -1049,6 +1138,7 @@ const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == ``` [⬆ back to top](#table-of-contents) + ### Value or default Returns value, or default value if passed value is `falsy`. @@ -1059,6 +1149,7 @@ const valueOrDefault = (value, d) => value || d; ``` [⬆ back to top](#table-of-contents) + ## Credits *Icons made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).* diff --git a/scripts/builder.js b/scripts/builder.js index 220469705..6a15e53a7 100644 --- a/scripts/builder.js +++ b/scripts/builder.js @@ -4,7 +4,10 @@ var path = require('path'); var snippetsPath = './snippets'; var staticPartsPath = './static-parts'; -var snippets = {}, startPart = '', endPart = '', output = ''; +var snippets = {}, startPart = '', endPart = '', output = '', tagDbData = {}; + +const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); +const capitalize = (str, lowerRest = false) => str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); console.time('Builder'); @@ -39,14 +42,28 @@ catch (err){ process.exit(1); } +try { + tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2))); +} +catch (err){ + console.log('Error during tag database loading: '+err); + process.exit(1); +} + try { output += `${startPart+'\n'}`; - for(var snippet of Object.entries(snippets)) - output += `* [${snippet[0][0].toUpperCase() + snippet[0].replace(/-/g,' ').slice(1,snippet[0].length-3)}](#${snippet[0].slice(0,snippet[0].length-3).replace(/\(/g,'').replace(/\)/g,'').toLowerCase()})\n` - output += '\n'; - for(var snippet of Object.entries(snippets)) - output += `${snippet[1]+'\n[⬆ back to top](#table-of-contents)\n'}`; - output += `${endPart+'\n'}`; + for(var tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].sort((a,b) => a.localeCompare(b))){ + output +=`### ${capitalize(tag, true)}\n`; + for(var taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag)) + output += `* [${taggedSnippet[0][0].toUpperCase() + taggedSnippet[0].replace(/-/g,' ').slice(1)}](#${taggedSnippet[0].replace(/\(/g,'').replace(/\)/g,'').toLowerCase()})\n` + output += '\n'; + } + for(var tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].sort((a,b) => a.localeCompare(b))){ + output +=`## ${capitalize(tag, true)}\n`; + for(var taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag)) + output += `\n${snippets[taggedSnippet[0]+'.md']+'\n[⬆ back to top](#table-of-contents)\n'}`; + } + output += `\n${endPart+'\n'}`; fs.writeFileSync('README.md', output); } catch (err){ diff --git a/scripts/tagger.js b/scripts/tagger.js index 6e2329e28..ecebce50f 100644 --- a/scripts/tagger.js +++ b/scripts/tagger.js @@ -35,11 +35,8 @@ catch (err){ } try { - tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').map(v => v.split(':').slice(0,2))); - // for(var tag of [...new Set(Object.entries(tagDbData).map(x => x[1]))]) - // tagDbStats[tag] = Object.values(tagDbData).filter(v => v === tag); - // console.log(tagDbStats); - tagDbStats = Object.entries(tagDbData).reduce((acc, val) => {acc.hasOwnProperty(val[1]) ? acc[val[1]]++ : acc[val[1]] = 1; return acc;}, {}); + tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2))); + tagDbStats = Object.entries(tagDbData).sort((a,b) => a[1].localeCompare(b[1])).reduce((acc, val) => {acc.hasOwnProperty(val[1]) ? acc[val[1]]++ : acc[val[1]] = 1; return acc;}, {}); } catch (err){ console.log('Error during tag database loading: '+err); @@ -61,7 +58,7 @@ catch (err){ console.log('Error during README generation: '+err); process.exit(1); } -console.log(`\n===Tag database statistics===`) +console.log(`\n=== TAG STATS ===`) for(var tagData of Object.entries(tagDbStats).filter(v => v[0] !== 'undefined')){ console.log(`${chalk.green(tagData[0])}: ${tagData[1]} snippets`); }