diff --git a/README.md b/README.md index 8d6d9000b..7cd979c7c 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,75 @@ -[![Logo](/logo.png)](https://30secondsofcode.org/) - -# 30 seconds of code - -[![License](https://img.shields.io/badge/license-CC0--1.0-blue.svg)](https://github.com/30-seconds/30-seconds-of-code/blob/master/LICENSE) [![npm Downloads](https://img.shields.io/npm/dt/30-seconds-of-code.svg)](https://www.npmjs.com/package/30-seconds-of-code) [![npm Version](https://img.shields.io/npm/v/30-seconds-of-code.svg)](https://www.npmjs.com/package/30-seconds-of-code) [![Known Vulnerabilities](https://snyk.io/test/github/30-seconds/30-seconds-of-code/badge.svg?targetFile=package.json)](https://snyk.io/test/github/30-seconds/30-seconds-of-code?targetFile=package.json)
-[![Travis Build](https://travis-ci.com/30-seconds/30-seconds-of-code.svg?branch=master)](https://travis-ci.com/30-seconds/30-seconds-of-code) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6ab7791fb1ea40b4a576d658fb96807f)](https://www.codacy.com/app/Chalarangelo/30-seconds-of-code?utm_source=github.com&utm_medium=referral&utm_content=30-seconds/30-seconds-of-code&utm_campaign=Badge_Grade) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard)
-[![Awesome](https://awesome.re/badge.svg)](https://awesome.re) [![ProductHunt](https://img.shields.io/badge/producthunt-vote-orange.svg)](https://www.producthunt.com/posts/30-seconds-of-code) [![Gitter chat](https://img.shields.io/badge/chat-on%20gitter-4FB999.svg)](https://gitter.im/30-seconds-of-code/Lobby) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) - -> Curated collection of useful JavaScript snippets that you can understand in 30 seconds or less. - -[![Sponsored by DigitalOcean](/sponsored_by_DigitalOcean.png)](https://www.digitalocean.com) - -* Use Ctrl + F or command + F to search for a snippet. -* Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). -* Snippets are written in ES6, use the [Babel transpiler](https://babeljs.io/) to ensure backwards-compatibility. -* You can import these snippets into VSCode, by following the instructions found [here](https://github.com/30-seconds/30-seconds-of-code/tree/master/vscode_snippets). -* You can search, view and copy these snippets from a terminal, using the CLI application from [this repo](https://github.com/sQVe/30s). -* If you want to follow 30-seconds-of-code on social media, you can find us on [Facebook](https://www.facebook.com/30secondsofcode), [Instagram](https://www.instagram.com/30secondsofcode) and [Twitter](https://twitter.com/30secondsofcode). - -#### Related projects - -* [30 Seconds of CSS](https://30-seconds.github.io/30-seconds-of-css/) -* [30 Seconds of Interviews](https://30secondsofinterviews.org/) -* [30 Seconds of React](https://github.com/30-seconds/30-seconds-of-react) -* [30 Seconds of Python](https://github.com/kriadmin/30-seconds-of-python-code) _(unofficial)_ -* [30 Seconds of PHP](https://github.com/appzcoder/30-seconds-of-php-code) _(unofficial)_ -* [30 Seconds of Kotlin](https://github.com/IvanMwiruki/30-seconds-of-kotlin) _(unofficial)_ -* [30 Seconds of Knowledge](https://chrome.google.com/webstore/detail/30-seconds-of-knowledge/mmgplondnjekobonklacmemikcnhklla) _(unofficial)_ - -#### Package - -⚠️ **NOTICE:** A few of our snippets are not yet optimized for production (see disclaimers for individual snippet issues). - -You can find a package with all the snippets on [npm](https://www.npmjs.com/package/30-seconds-of-code). - -```bash -# With npm -npm install 30-seconds-of-code - -# With yarn -yarn add 30-seconds-of-code -``` - -[CDN link](https://unpkg.com/30-seconds-of-code/) - -
-Details - -**Browser** - -```html - - -``` - -**Node** - -```js -// CommonJS -const _30s = require('30-seconds-of-code'); -_30s.average(1, 2, 3); - -// ES Modules -import _30s from '30-seconds-of-code'; -_30s.average(1, 2, 3); -``` - -
- -## Contents +[![Logo](/logo.png)](https://30secondsofcode.org/) + +# 30 seconds of code + +[![License](https://img.shields.io/badge/license-CC0--1.0-blue.svg)](https://github.com/30-seconds/30-seconds-of-code/blob/master/LICENSE) [![npm Downloads](https://img.shields.io/npm/dt/30-seconds-of-code.svg)](https://www.npmjs.com/package/30-seconds-of-code) [![npm Version](https://img.shields.io/npm/v/30-seconds-of-code.svg)](https://www.npmjs.com/package/30-seconds-of-code) [![Known Vulnerabilities](https://snyk.io/test/github/30-seconds/30-seconds-of-code/badge.svg?targetFile=package.json)](https://snyk.io/test/github/30-seconds/30-seconds-of-code?targetFile=package.json)
+[![Travis Build](https://travis-ci.com/30-seconds/30-seconds-of-code.svg?branch=master)](https://travis-ci.com/30-seconds/30-seconds-of-code) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6ab7791fb1ea40b4a576d658fb96807f)](https://www.codacy.com/app/Chalarangelo/30-seconds-of-code?utm_source=github.com&utm_medium=referral&utm_content=30-seconds/30-seconds-of-code&utm_campaign=Badge_Grade) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/Flet/semistandard)
+[![Awesome](https://awesome.re/badge.svg)](https://awesome.re) [![ProductHunt](https://img.shields.io/badge/producthunt-vote-orange.svg)](https://www.producthunt.com/posts/30-seconds-of-code) [![Gitter chat](https://img.shields.io/badge/chat-on%20gitter-4FB999.svg)](https://gitter.im/30-seconds-of-code/Lobby) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) + +> Curated collection of useful JavaScript snippets that you can understand in 30 seconds or less. + +[![Sponsored by DigitalOcean](/sponsored_by_DigitalOcean.png)](https://www.digitalocean.com) + +* Use Ctrl + F or command + F to search for a snippet. +* Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). +* Snippets are written in ES6, use the [Babel transpiler](https://babeljs.io/) to ensure backwards-compatibility. +* You can import these snippets into VSCode, by following the instructions found [here](https://github.com/30-seconds/30-seconds-of-code/tree/master/vscode_snippets). +* You can search, view and copy these snippets from a terminal, using the CLI application from [this repo](https://github.com/sQVe/30s). +* If you want to follow 30-seconds-of-code on social media, you can find us on [Facebook](https://www.facebook.com/30secondsofcode), [Instagram](https://www.instagram.com/30secondsofcode) and [Twitter](https://twitter.com/30secondsofcode). + +#### Related projects + +* [30 Seconds of CSS](https://30-seconds.github.io/30-seconds-of-css/) +* [30 Seconds of Interviews](https://30secondsofinterviews.org/) +* [30 Seconds of React](https://github.com/30-seconds/30-seconds-of-react) +* [30 Seconds of Python](https://github.com/kriadmin/30-seconds-of-python-code) _(unofficial)_ +* [30 Seconds of PHP](https://github.com/appzcoder/30-seconds-of-php-code) _(unofficial)_ +* [30 Seconds of Kotlin](https://github.com/IvanMwiruki/30-seconds-of-kotlin) _(unofficial)_ +* [30 Seconds of Knowledge](https://chrome.google.com/webstore/detail/30-seconds-of-knowledge/mmgplondnjekobonklacmemikcnhklla) _(unofficial)_ + +#### Package + +⚠️ **NOTICE:** A few of our snippets are not yet optimized for production (see disclaimers for individual snippet issues). + +You can find a package with all the snippets on [npm](https://www.npmjs.com/package/30-seconds-of-code). + +```bash +# With npm +npm install 30-seconds-of-code + +# With yarn +yarn add 30-seconds-of-code +``` + +[CDN link](https://unpkg.com/30-seconds-of-code/) + +
+Details + +**Browser** + +```html + + +``` + +**Node** + +```js +// CommonJS +const _30s = require('30-seconds-of-code'); +_30s.average(1, 2, 3); + +// ES Modules +import _30s from '30-seconds-of-code'; +_30s.average(1, 2, 3); +``` + +
+ +## Contents ### 🔌 Adapter @@ -314,6 +314,7 @@ _30s.average(1, 2, 3); * [`isPrime`](#isprime) * [`lcm`](#lcm) * [`luhnCheck`](#luhncheck-) +* [`mapNumRange`](#mapnumrange) * [`maxBy`](#maxby) * [`median`](#median) * [`midpoint`](#midpoint) @@ -505,12 +506,12 @@ _30s.average(1, 2, 3); ## 🔌 Adapter -### ary - -Creates a function that accepts up to `n` arguments, ignoring any additional arguments. - -Call the provided function, `fn`, with up to `n` arguments, using `Array.prototype.slice(0,n)` and the spread operator (`...`). - +### ary + +Creates a function that accepts up to `n` arguments, ignoring any additional arguments. + +Call the provided function, `fn`, with up to `n` arguments, using `Array.prototype.slice(0,n)` and the spread operator (`...`). + ```js const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); ``` @@ -521,7 +522,7 @@ const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); ```js const firstTwoMax = ary(Math.max, 2); [[2, 6, 'a'], [8, 4, 6], [10]].map(x => firstTwoMax(...x)); // [6, 8, 10] -``` +``` @@ -606,12 +607,12 @@ Object.assign(b, a); // == b
[⬆ Back to top](#contents) -### over - -Creates a function that invokes each provided function with the arguments it receives and returns the results. - -Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments. - +### over + +Creates a function that invokes each provided function with the arguments it receives and returns the results. + +Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments. + ```js const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); ``` @@ -622,18 +623,18 @@ const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); ```js const minMax = over(Math.min, Math.max); minMax(1, 2, 3, 4, 5); // [1,5] -``` +```
[⬆ Back to top](#contents) -### overArgs - -Creates a function that invokes the provided function with its arguments transformed. - -Use `Array.prototype.map()` to apply `transforms` to `args` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`. - +### overArgs + +Creates a function that invokes the provided function with its arguments transformed. + +Use `Array.prototype.map()` to apply `transforms` to `args` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`. + ```js const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); ``` @@ -646,51 +647,51 @@ const square = n => n * n; const double = n => n * 2; const fn = overArgs((x, y) => [x, y], [square, double]); fn(9, 3); // [81, 6] -``` +```
[⬆ Back to top](#contents) -### pipeAsyncFunctions - -Performs left-to-right function composition for asynchronous functions. - -Use `Array.prototype.reduce()` with the spread operator (`...`) to perform left-to-right function composition using `Promise.then()`. -The functions can return a combination of: simple values, `Promise`'s, or they can be defined as `async` ones returning through `await`. -All functions must be unary. - -```js -const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); +### pipeAsyncFunctions + +Performs left-to-right function composition for asynchronous functions. + +Use `Array.prototype.reduce()` with the spread operator (`...`) to perform left-to-right function composition using `Promise.then()`. +The functions can return a combination of: simple values, `Promise`'s, or they can be defined as `async` ones returning through `await`. +All functions must be unary. + +```js +const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); ```
Examples -```js - -const sum = pipeAsyncFunctions( - x => x + 1, - x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)), - x => x + 3, - async x => (await x) + 4 -); -(async() => { - console.log(await sum(5)); // 15 (after one second) -})(); -``` +```js + +const sum = pipeAsyncFunctions( + x => x + 1, + x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)), + x => x + 3, + async x => (await x) + 4 +); +(async() => { + console.log(await sum(5)); // 15 (after one second) +})(); +```

[⬆ Back to top](#contents) -### pipeFunctions - -Performs left-to-right function composition. - -Use `Array.prototype.reduce()` with the spread operator (`...`) to perform left-to-right function composition. -The first (leftmost) function can accept one or more arguments; the remaining functions must be unary. - +### pipeFunctions + +Performs left-to-right function composition. + +Use `Array.prototype.reduce()` with the spread operator (`...`) to perform left-to-right function composition. +The first (leftmost) function can accept one or more arguments; the remaining functions must be unary. + ```js const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); ``` @@ -703,21 +704,21 @@ const add5 = x => x + 5; const multiply = (x, y) => x * y; const multiplyAndAdd5 = pipeFunctions(multiply, add5); multiplyAndAdd5(5, 2); // 15 -``` +```
[⬆ Back to top](#contents) -### promisify - -Converts an asynchronous function to return a promise. - -Use currying to return a function returning a `Promise` that calls the original function. -Use the `...rest` operator to pass in all the parameters. - -*In Node 8+, you can use [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original)* - +### promisify + +Converts an asynchronous function to return a promise. + +Use currying to return a function returning a `Promise` that calls the original function. +Use the `...rest` operator to pass in all the parameters. + +*In Node 8+, you can use [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original)* + ```js const promisify = func => (...args) => new Promise((resolve, reject) => @@ -731,18 +732,18 @@ const promisify = func => (...args) => ```js const delay = promisify((d, cb) => setTimeout(cb, d)); delay(2000).then(() => console.log('Hi!')); // // Promise resolves after 2s -``` +```
[⬆ Back to top](#contents) -### rearg - -Creates a function that invokes the provided function with its arguments arranged according to the specified indexes. - -Use `Array.prototype.map()` to reorder arguments based on `indexes` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`. - +### rearg + +Creates a function that invokes the provided function with its arguments arranged according to the specified indexes. + +Use `Array.prototype.map()` to reorder arguments based on `indexes` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`. + ```js const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); ``` @@ -758,7 +759,7 @@ var rearged = rearg( [2, 0, 1] ); rearged('b', 'c', 'a'); // ['a', 'b', 'c'] -``` +``` @@ -786,12 +787,12 @@ arrayMax([1, 2, 3]); // 3
[⬆ Back to top](#contents) -### unary - -Creates a function that accepts up to one argument, ignoring any additional arguments. - -Call the provided function, `fn`, with just the first argument given. - +### unary + +Creates a function that accepts up to one argument, ignoring any additional arguments. + +Call the provided function, `fn`, with just the first argument given. + ```js const unary = fn => val => fn(val); ``` @@ -801,7 +802,7 @@ const unary = fn => val => fn(val); ```js ['6', '8', '10'].map(unary(parseInt)); // [6, 8, 10] -``` +``` @@ -812,13 +813,13 @@ const unary = fn => val => fn(val); ## 📚 Array -### all - -Returns `true` if the provided predicate function returns `true` for all elements in a collection, `false` otherwise. - -Use `Array.prototype.every()` to test if all elements in the collection return `true` based on `fn`. -Omit the second argument, `fn`, to use `Boolean` as a default. - +### all + +Returns `true` if the provided predicate function returns `true` for all elements in a collection, `false` otherwise. + +Use `Array.prototype.every()` to test if all elements in the collection return `true` based on `fn`. +Omit the second argument, `fn`, to use `Boolean` as a default. + ```js const all = (arr, fn = Boolean) => arr.every(fn); ``` @@ -829,18 +830,18 @@ const all = (arr, fn = Boolean) => arr.every(fn); ```js all([4, 2, 3], x => x > 1); // true all([1, 2, 3]); // true -``` +```
[⬆ Back to top](#contents) -### allEqual - -Check if all elements in an array are equal. - -Use `Array.prototype.every()` to check if all the elements of the array are the same as the first one. - +### allEqual + +Check if all elements in an array are equal. + +Use `Array.prototype.every()` to check if all the elements of the array are the same as the first one. + ```js const allEqual = arr => arr.every(val => val === arr[0]); ``` @@ -851,19 +852,19 @@ const allEqual = arr => arr.every(val => val === arr[0]); ```js allEqual([1, 2, 3, 4, 5, 6]); // false allEqual([1, 1, 1, 1]); // true -``` +```
[⬆ Back to top](#contents) -### any - -Returns `true` if the provided predicate function returns `true` for at least one element in a collection, `false` otherwise. - -Use `Array.prototype.some()` to test if any elements in the collection return `true` based on `fn`. -Omit the second argument, `fn`, to use `Boolean` as a default. - +### any + +Returns `true` if the provided predicate function returns `true` for at least one element in a collection, `false` otherwise. + +Use `Array.prototype.some()` to test if any elements in the collection return `true` based on `fn`. +Omit the second argument, `fn`, to use `Boolean` as a default. + ```js const any = (arr, fn = Boolean) => arr.some(fn); ``` @@ -874,20 +875,20 @@ const any = (arr, fn = Boolean) => arr.some(fn); ```js any([0, 1, 2, 0], x => x >= 2); // true any([0, 0, 1, 0]); // true -``` +```
[⬆ Back to top](#contents) -### arrayToCSV - -Converts a 2D array to a comma-separated values (CSV) string. - -Use `Array.prototype.map()` and `Array.prototype.join(delimiter)` to combine individual 1D arrays (rows) into strings. -Use `Array.prototype.join('\n')` to combine all rows into a CSV string, separating each row with a newline. -Omit the second argument, `delimiter`, to use a default delimiter of `,`. - +### arrayToCSV + +Converts a 2D array to a comma-separated values (CSV) string. + +Use `Array.prototype.map()` and `Array.prototype.join(delimiter)` to combine individual 1D arrays (rows) into strings. +Use `Array.prototype.join('\n')` to combine all rows into a CSV string, separating each row with a newline. +Omit the second argument, `delimiter`, to use a default delimiter of `,`. + ```js const arrayToCSV = (arr, delimiter = ',') => arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n'); @@ -899,18 +900,18 @@ const arrayToCSV = (arr, delimiter = ',') => ```js arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"' arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"' -``` +```
[⬆ Back to top](#contents) -### bifurcate - -Splits values into two groups. If an element in `filter` is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group. - -Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on `filter`. - +### bifurcate + +Splits values into two groups. If an element in `filter` is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group. + +Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on `filter`. + ```js const bifurcate = (arr, filter) => arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); @@ -921,18 +922,18 @@ const bifurcate = (arr, filter) => ```js bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); // [ ['beep', 'boop', 'bar'], ['foo'] ] -``` +```
[⬆ Back to top](#contents) -### bifurcateBy - -Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group. - -Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on the value returned by `fn` for each element. - +### bifurcateBy + +Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group. + +Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on the value returned by `fn` for each element. + ```js const bifurcateBy = (arr, fn) => arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); @@ -943,20 +944,20 @@ const bifurcateBy = (arr, fn) => ```js bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ] -``` +```
[⬆ Back to top](#contents) -### chunk - -Chunks an array into smaller arrays of a specified size. - -Use `Array.from()` to create a new array, that fits the number of chunks that will be produced. -Use `Array.prototype.slice()` to map each element of the new array to a chunk the length of `size`. -If the original array can't be split evenly, the final chunk will contain the remaining elements. - +### chunk + +Chunks an array into smaller arrays of a specified size. + +Use `Array.from()` to create a new array, that fits the number of chunks that will be produced. +Use `Array.prototype.slice()` to map each element of the new array to a chunk the length of `size`. +If the original array can't be split evenly, the final chunk will contain the remaining elements. + ```js const chunk = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => @@ -969,18 +970,18 @@ const chunk = (arr, size) => ```js chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]] -``` +```
[⬆ Back to top](#contents) -### compact - -Removes falsey values from an array. - -Use `Array.prototype.filter()` to filter out falsey values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`). - +### compact + +Removes falsey values from an array. + +Use `Array.prototype.filter()` to filter out falsey values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`). + ```js const compact = arr => arr.filter(Boolean); ``` @@ -990,45 +991,45 @@ const compact = arr => arr.filter(Boolean); ```js compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); // [ 1, 2, 3, 'a', 's', 34 ] -``` +```
[⬆ Back to top](#contents) -### countBy - -Groups the elements of an array based on the given function and returns the count of elements in each group. - -Use `Array.prototype.map()` to map the values of an array to a function or property name. -Use `Array.prototype.reduce()` to create an object, where the keys are produced from the mapped results. - +### countBy + +Groups the elements of an array based on the given function and returns the count of elements in each group. + +Use `Array.prototype.map()` to map the values of an array to a function or property name. +Use `Array.prototype.reduce()` to create an object, where the keys are produced from the mapped results. + ```js -const countBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { - acc[val] = (acc[val] || 0) + 1; - return acc; - }, {}); +const countBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { + acc[val] = (acc[val] || 0) + 1; + return acc; + }, {}); ```
Examples ```js -countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2} -countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1} -``` +countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2} +countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1} +```

[⬆ Back to top](#contents) -### countOccurrences - -Counts the occurrences of a value in an array. - -Use `Array.prototype.reduce()` to increment a counter each time you encounter the specific value inside the array. - +### countOccurrences + +Counts the occurrences of a value in an array. + +Use `Array.prototype.reduce()` to increment a counter each time you encounter the specific value inside the array. + ```js const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); ``` @@ -1038,20 +1039,20 @@ const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : ```js countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3 -``` +```
[⬆ Back to top](#contents) -### deepFlatten - -Deep flattens an array. - -Use recursion. -Use `Array.prototype.concat()` with an empty array (`[]`) and the spread operator (`...`) to flatten an array. -Recursively flatten each element that is an array. - +### deepFlatten + +Deep flattens an array. + +Use recursion. +Use `Array.prototype.concat()` with an empty array (`[]`) and the spread operator (`...`) to flatten an array. +Recursively flatten each element that is an array. + ```js const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); ``` @@ -1061,18 +1062,18 @@ const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFla ```js deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5] -``` +```
[⬆ Back to top](#contents) -### difference - -Returns the difference between two arrays. - -Create a `Set` from `b`, then use `Array.prototype.filter()` on `a` to only keep values not contained in `b`. - +### difference + +Returns the difference between two arrays. + +Create a `Set` from `b`, then use `Array.prototype.filter()` on `a` to only keep values not contained in `b`. + ```js const difference = (a, b) => { const s = new Set(b); @@ -1085,43 +1086,43 @@ const difference = (a, b) => { ```js difference([1, 2, 3], [1, 2, 4]); // [3] -``` +```
[⬆ Back to top](#contents) -### differenceBy - -Returns the difference between two arrays, after applying the provided function to each array element of both. - -Create a `Set` by applying `fn` to each element in `b`, then use `Array.prototype.filter()` in combination with `fn` on `a` to only keep values not contained in the previously created set. - +### differenceBy + +Returns the difference between two arrays, after applying the provided function to each array element of both. + +Create a `Set` by applying `fn` to each element in `b`, then use `Array.prototype.filter()` in combination with `fn` on `a` to only keep values not contained in the previously created set. + ```js -const differenceBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => !s.has(fn(x))); -}; +const differenceBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => !s.has(fn(x))); +}; ```
Examples ```js -differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2] -differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ] -``` +differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2] +differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ] +```

[⬆ Back to top](#contents) -### differenceWith - -Filters out all values from an array for which the comparator function does not return `true`. - -Use `Array.prototype.filter()` and `Array.prototype.findIndex()` to find the appropriate values. - +### differenceWith + +Filters out all values from an array for which the comparator function does not return `true`. + +Use `Array.prototype.filter()` and `Array.prototype.findIndex()` to find the appropriate values. + ```js const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); ``` @@ -1131,18 +1132,18 @@ const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => co ```js differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2] -``` +```
[⬆ Back to top](#contents) -### drop - -Returns a new array with `n` elements removed from the left. - -Use `Array.prototype.slice()` to slice the remove the specified number of elements from the left. - +### drop + +Returns a new array with `n` elements removed from the left. + +Use `Array.prototype.slice()` to slice the remove the specified number of elements from the left. + ```js const drop = (arr, n = 1) => arr.slice(n); ``` @@ -1154,18 +1155,18 @@ const drop = (arr, n = 1) => arr.slice(n); drop([1, 2, 3]); // [2,3] drop([1, 2, 3], 2); // [3] drop([1, 2, 3], 42); // [] -``` +```
[⬆ Back to top](#contents) -### dropRight - -Returns a new array with `n` elements removed from the right. - -Use `Array.prototype.slice()` to slice the remove the specified number of elements from the right. - +### dropRight + +Returns a new array with `n` elements removed from the right. + +Use `Array.prototype.slice()` to slice the remove the specified number of elements from the right. + ```js const dropRight = (arr, n = 1) => arr.slice(0, -n); ``` @@ -1177,19 +1178,19 @@ const dropRight = (arr, n = 1) => arr.slice(0, -n); dropRight([1, 2, 3]); // [1,2] dropRight([1, 2, 3], 2); // [1] dropRight([1, 2, 3], 42); // [] -``` +```
[⬆ Back to top](#contents) -### dropRightWhile - -Removes elements from the end of an array until the passed function returns `true`. Returns the remaining elements in the array. - -Loop through the array, using `Array.prototype.slice()` to drop the last element of the array until the returned value from the function is `true`. -Returns the remaining elements. - +### dropRightWhile + +Removes elements from the end of an array until the passed function returns `true`. Returns the remaining elements in the array. + +Loop through the array, using `Array.prototype.slice()` to drop the last element of the array until the returned value from the function is `true`. +Returns the remaining elements. + ```js const dropRightWhile = (arr, func) => { while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); @@ -1202,19 +1203,19 @@ const dropRightWhile = (arr, func) => { ```js dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2] -``` +```
[⬆ Back to top](#contents) -### dropWhile - -Removes elements in an array until the passed function returns `true`. Returns the remaining elements in the array. - -Loop through the array, using `Array.prototype.slice()` to drop the first element of the array until the returned value from the function is `true`. -Returns the remaining elements. - +### dropWhile + +Removes elements in an array until the passed function returns `true`. Returns the remaining elements in the array. + +Loop through the array, using `Array.prototype.slice()` to drop the first element of the array until the returned value from the function is `true`. +Returns the remaining elements. + ```js const dropWhile = (arr, func) => { while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); @@ -1227,18 +1228,18 @@ const dropWhile = (arr, func) => { ```js dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4] -``` +```
[⬆ Back to top](#contents) -### everyNth - -Returns every nth element in an array. - -Use `Array.prototype.filter()` to create a new array that contains every nth element of a given array. - +### everyNth + +Returns every nth element in an array. + +Use `Array.prototype.filter()` to create a new array that contains every nth element of a given array. + ```js const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); ``` @@ -1248,7 +1249,7 @@ const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); ```js everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ] -``` +``` @@ -1275,12 +1276,12 @@ filterFalsy(['', true, {}, false, 'sample', 1, 0]); // [true, {}, 'sample', 1]
[⬆ Back to top](#contents) -### filterNonUnique - -Filters out the non-unique values in an array. - -Use `Array.prototype.filter()` for an array containing only the unique values. - +### filterNonUnique + +Filters out the non-unique values in an array. + +Use `Array.prototype.filter()` for an array containing only the unique values. + ```js const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); ``` @@ -1290,19 +1291,19 @@ const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexO ```js filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5] -``` +```
[⬆ Back to top](#contents) -### filterNonUniqueBy - -Filters out the non-unique values in an array, based on a provided comparator function. - -Use `Array.prototype.filter()` and `Array.prototype.every()` for an array containing only the unique values, based on the comparator function, `fn`. -The comparator function takes four arguments: the values of the two elements being compared and their indexes. - +### filterNonUniqueBy + +Filters out the non-unique values in an array, based on a provided comparator function. + +Use `Array.prototype.filter()` and `Array.prototype.every()` for an array containing only the unique values, based on the comparator function, `fn`. +The comparator function takes four arguments: the values of the two elements being compared and their indexes. + ```js const filterNonUniqueBy = (arr, fn) => arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); @@ -1322,18 +1323,18 @@ filterNonUniqueBy( ], (a, b) => a.id == b.id ); // [ { id: 2, value: 'c' } ] -``` +```
[⬆ Back to top](#contents) -### findLast - -Returns the last element for which the provided function returns a truthy value. - -Use `Array.prototype.filter()` to remove elements for which `fn` returns falsey values, `Array.prototype.pop()` to get the last one. - +### findLast + +Returns the last element for which the provided function returns a truthy value. + +Use `Array.prototype.filter()` to remove elements for which `fn` returns falsey values, `Array.prototype.pop()` to get the last one. + ```js const findLast = (arr, fn) => arr.filter(fn).pop(); ``` @@ -1343,19 +1344,19 @@ const findLast = (arr, fn) => arr.filter(fn).pop(); ```js findLast([1, 2, 3, 4], n => n % 2 === 1); // 3 -``` +```
[⬆ Back to top](#contents) -### findLastIndex - -Returns the index of the last element for which the provided function returns a truthy value. - -Use `Array.prototype.map()` to map each element to an array with its index and value. -Use `Array.prototype.filter()` to remove elements for which `fn` returns falsey values, `Array.prototype.pop()` to get the last one. - +### findLastIndex + +Returns the index of the last element for which the provided function returns a truthy value. + +Use `Array.prototype.map()` to map each element to an array with its index and value. +Use `Array.prototype.filter()` to remove elements for which `fn` returns falsey values, `Array.prototype.pop()` to get the last one. + ```js const findLastIndex = (arr, fn) => arr @@ -1369,21 +1370,21 @@ const findLastIndex = (arr, fn) => ```js findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3) -``` +```
[⬆ Back to top](#contents) -### flatten - -Flattens an array up to the specified depth. - -Use recursion, decrementing `depth` by 1 for each level of depth. -Use `Array.prototype.reduce()` and `Array.prototype.concat()` to merge elements or arrays. -Base case, for `depth` equal to `1` stops recursion. -Omit the second argument, `depth` to flatten only to a depth of `1` (single flatten). - +### flatten + +Flattens an array up to the specified depth. + +Use recursion, decrementing `depth` by 1 for each level of depth. +Use `Array.prototype.reduce()` and `Array.prototype.concat()` to merge elements or arrays. +Base case, for `depth` equal to `1` stops recursion. +Omit the second argument, `depth` to flatten only to a depth of `1` (single flatten). + ```js const flatten = (arr, depth = 1) => arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); @@ -1395,18 +1396,18 @@ const flatten = (arr, depth = 1) => ```js flatten([1, [2], 3, 4]); // [1, 2, 3, 4] flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8] -``` +```
[⬆ Back to top](#contents) -### forEachRight - -Executes a provided function once for each array element, starting from the array's last element. - -Use `Array.prototype.slice(0)` to clone the given array, `Array.prototype.reverse()` to reverse it and `Array.prototype.forEach()` to iterate over the reversed array. - +### forEachRight + +Executes a provided function once for each array element, starting from the array's last element. + +Use `Array.prototype.slice(0)` to clone the given array, `Array.prototype.reverse()` to reverse it and `Array.prototype.forEach()` to iterate over the reversed array. + ```js const forEachRight = (arr, callback) => arr @@ -1420,19 +1421,19 @@ const forEachRight = (arr, callback) => ```js forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1' -``` +```
[⬆ Back to top](#contents) -### groupBy - -Groups the elements of an array based on the given function. - -Use `Array.prototype.map()` to map the values of an array to a function or property name. -Use `Array.prototype.reduce()` to create an object, where the keys are produced from the mapped results. - +### groupBy + +Groups the elements of an array based on the given function. + +Use `Array.prototype.map()` to map the values of an array to a function or property name. +Use `Array.prototype.reduce()` to create an object, where the keys are produced from the mapped results. + ```js const groupBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { @@ -1447,18 +1448,18 @@ const groupBy = (arr, fn) => ```js 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](#contents) -### head - -Returns the head of a list. - -Use `arr[0]` to return the first element of the passed array. - +### head + +Returns the head of a list. + +Use `arr[0]` to return the first element of the passed array. + ```js const head = arr => arr[0]; ``` @@ -1468,20 +1469,20 @@ const head = arr => arr[0]; ```js head([1, 2, 3]); // 1 -``` +```
[⬆ Back to top](#contents) -### indexOfAll - -Returns all indices of `val` in an array. -If `val` never occurs, returns `[]`. - -Use `Array.prototype.reduce()` to loop over elements and store indices for matching elements. -Return the array of indices. - +### indexOfAll + +Returns all indices of `val` in an array. +If `val` never occurs, returns `[]`. + +Use `Array.prototype.reduce()` to loop over elements and store indices for matching elements. +Return the array of indices. + ```js const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); ``` @@ -1492,18 +1493,18 @@ const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...ac ```js indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3] indexOfAll([1, 2, 3], 4); // [] -``` +```
[⬆ Back to top](#contents) -### initial - -Returns all the elements of an array except the last one. - -Use `arr.slice(0,-1)` to return all but the last element of the array. - +### initial + +Returns all the elements of an array except the last one. + +Use `arr.slice(0,-1)` to return all but the last element of the array. + ```js const initial = arr => arr.slice(0, -1); ``` @@ -1513,18 +1514,18 @@ const initial = arr => arr.slice(0, -1); ```js initial([1, 2, 3]); // [1,2] -``` +```
[⬆ Back to top](#contents) -### initialize2DArray - -Initializes a 2D array of given width and height and value. - -Use `Array.prototype.map()` to generate h rows where each is a new array of size w initialize with value. If the value is not provided, default to `null`. - +### initialize2DArray + +Initializes a 2D array of given width and height and value. + +Use `Array.prototype.map()` to generate h rows where each is a new array of size w initialize with value. If the value is not provided, default to `null`. + ```js const initialize2DArray = (w, h, val = null) => Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); @@ -1535,20 +1536,20 @@ const initialize2DArray = (w, h, val = null) => ```js initialize2DArray(2, 2, 0); // [[0,0], [0,0]] -``` +```
[⬆ Back to top](#contents) -### initializeArrayWithRange - -Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive with their common difference `step`. - -Use `Array.from()` to create an array of the desired length, `(end - start + 1)/step`, and a map function to fill it with the desired values in the given range. -You can omit `start` to use a default value of `0`. -You can omit `step` to use a default value of `1`. - +### initializeArrayWithRange + +Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive with their common difference `step`. + +Use `Array.from()` to create an array of the desired length, `(end - start + 1)/step`, and a map function to fill it with the desired values in the given range. +You can omit `start` to use a default value of `0`. +You can omit `step` to use a default value of `1`. + ```js const initializeArrayWithRange = (end, start = 0, step = 1) => Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); @@ -1561,20 +1562,20 @@ const initializeArrayWithRange = (end, start = 0, step = 1) => initializeArrayWithRange(5); // [0,1,2,3,4,5] initializeArrayWithRange(7, 3); // [3,4,5,6,7] initializeArrayWithRange(9, 0, 2); // [0,2,4,6,8] -``` +```
[⬆ Back to top](#contents) -### initializeArrayWithRangeRight - -Initializes an array containing the numbers in the specified range (in reverse) where `start` and `end` are inclusive with their common difference `step`. - -Use `Array.from(Math.ceil((end+1-start)/step))` to create an array of the desired length(the amounts of elements is equal to `(end-start)/step` or `(end+1-start)/step` for inclusive end), `Array.prototype.map()` to fill with the desired values in a range. -You can omit `start` to use a default value of `0`. -You can omit `step` to use a default value of `1`. - +### initializeArrayWithRangeRight + +Initializes an array containing the numbers in the specified range (in reverse) where `start` and `end` are inclusive with their common difference `step`. + +Use `Array.from(Math.ceil((end+1-start)/step))` to create an array of the desired length(the amounts of elements is equal to `(end-start)/step` or `(end+1-start)/step` for inclusive end), `Array.prototype.map()` to fill with the desired values in a range. +You can omit `start` to use a default value of `0`. +You can omit `step` to use a default value of `1`. + ```js const initializeArrayWithRangeRight = (end, start = 0, step = 1) => Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( @@ -1589,19 +1590,19 @@ const initializeArrayWithRangeRight = (end, start = 0, step = 1) => initializeArrayWithRangeRight(5); // [5,4,3,2,1,0] initializeArrayWithRangeRight(7, 3); // [7,6,5,4,3] initializeArrayWithRangeRight(9, 0, 2); // [8,6,4,2,0] -``` +```
[⬆ Back to top](#contents) -### initializeArrayWithValues - -Initializes and fills an array with the specified values. - -Use `Array(n)` to create an array of the desired length, `fill(v)` to fill it with the desired values. -You can omit `val` to use a default value of `0`. - +### initializeArrayWithValues + +Initializes and fills an array with the specified values. + +Use `Array(n)` to create an array of the desired length, `fill(v)` to fill it with the desired values. +You can omit `val` to use a default value of `0`. + ```js const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); ``` @@ -1611,19 +1612,19 @@ const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); ```js initializeArrayWithValues(5, 2); // [2, 2, 2, 2, 2] -``` +```
[⬆ Back to top](#contents) -### initializeNDArray - -Create a n-dimensional array with given value. - -Use recursion. -Use `Array.prototype.map()` to generate rows where each is a new array initialized using `initializeNDArray`. - +### initializeNDArray + +Create a n-dimensional array with given value. + +Use recursion. +Use `Array.prototype.map()` to generate rows where each is a new array initialized using `initializeNDArray`. + ```js const initializeNDArray = (val, ...args) => args.length === 0 @@ -1637,18 +1638,18 @@ const initializeNDArray = (val, ...args) => ```js initializeNDArray(1, 3); // [1,1,1] initializeNDArray(5, 2, 2, 2); // [[[5,5],[5,5]],[[5,5],[5,5]]] -``` +```
[⬆ Back to top](#contents) -### intersection - -Returns a list of elements that exist in both arrays. - -Create a `Set` from `b`, then use `Array.prototype.filter()` on `a` to only keep values contained in `b`. - +### intersection + +Returns a list of elements that exist in both arrays. + +Create a `Set` from `b`, then use `Array.prototype.filter()` on `a` to only keep values contained in `b`. + ```js const intersection = (a, b) => { const s = new Set(b); @@ -1661,18 +1662,18 @@ const intersection = (a, b) => { ```js intersection([1, 2, 3], [4, 3, 2]); // [2, 3] -``` +```
[⬆ Back to top](#contents) -### intersectionBy - -Returns a list of elements that exist in both arrays, after applying the provided function to each array element of both. - -Create a `Set` by applying `fn` to all elements in `b`, then use `Array.prototype.filter()` on `a` to only keep elements, which produce values contained in `b` when `fn` is applied to them. - +### intersectionBy + +Returns a list of elements that exist in both arrays, after applying the provided function to each array element of both. + +Create a `Set` by applying `fn` to all elements in `b`, then use `Array.prototype.filter()` on `a` to only keep elements, which produce values contained in `b` when `fn` is applied to them. + ```js const intersectionBy = (a, b, fn) => { const s = new Set(b.map(fn)); @@ -1685,18 +1686,18 @@ const intersectionBy = (a, b, fn) => { ```js intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1] -``` +```
[⬆ Back to top](#contents) -### intersectionWith - -Returns a list of elements that exist in both arrays, using a provided comparator function. - -Use `Array.prototype.filter()` and `Array.prototype.findIndex()` in combination with the provided comparator to determine intersecting values. - +### intersectionWith + +Returns a list of elements that exist in both arrays, using a provided comparator function. + +Use `Array.prototype.filter()` and `Array.prototype.findIndex()` in combination with the provided comparator to determine intersecting values. + ```js const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); ``` @@ -1706,20 +1707,20 @@ const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, ```js intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0] -``` +```
[⬆ Back to top](#contents) -### isSorted - -Returns `1` if the array is sorted in ascending order, `-1` if it is sorted in descending order or `0` if it is not sorted. - -Calculate the ordering `direction` for the first two elements. -Use `Object.entries()` to loop over array objects and compare them in pairs. -Return `0` if the `direction` changes or the `direction` if the last element is reached. - +### isSorted + +Returns `1` if the array is sorted in ascending order, `-1` if it is sorted in descending order or `0` if it is not sorted. + +Calculate the ordering `direction` for the first two elements. +Use `Object.entries()` to loop over array objects and compare them in pairs. +Return `0` if the `direction` changes or the `direction` if the last element is reached. + ```js const isSorted = arr => { let direction = -(arr[0] - arr[1]); @@ -1738,21 +1739,21 @@ const isSorted = arr => { isSorted([0, 1, 2, 2]); // 1 isSorted([4, 3, 2]); // -1 isSorted([4, 3, 5]); // 0 -``` +```
[⬆ Back to top](#contents) -### join - -Joins all elements of an array into a string and returns this string. -Uses a separator and an end separator. - -Use `Array.prototype.reduce()` to combine elements into a string. -Omit the second argument, `separator`, to use a default separator of `','`. -Omit the third argument, `end`, to use the same value as `separator` by default. - +### join + +Joins all elements of an array into a string and returns this string. +Uses a separator and an end separator. + +Use `Array.prototype.reduce()` to combine elements into a string. +Omit the second argument, `separator`, to use a default separator of `','`. +Omit the third argument, `end`, to use the same value as `separator` by default. + ```js const join = (arr, separator = ',', end = separator) => arr.reduce( @@ -1773,7 +1774,7 @@ const join = (arr, separator = ',', end = separator) => join(['pen', 'pineapple', 'apple', 'pen'], ',', '&'); // "pen,pineapple,apple&pen" join(['pen', 'pineapple', 'apple', 'pen'], ','); // "pen,pineapple,apple,pen" join(['pen', 'pineapple', 'apple', 'pen']); // "pen,pineapple,apple,pen" -``` +``` @@ -1813,12 +1814,12 @@ JSONtoCSV([{ a: 1, b: 2 }, { a: 3, b: 4, c: 5 }, { a: 6 }, { b: 7 }], ['a', 'b']
[⬆ Back to top](#contents) -### last - -Returns the last element in an array. - -Use `arr.length - 1` to compute the index of the last element of the given array and returning it. - +### last + +Returns the last element in an array. + +Use `arr.length - 1` to compute the index of the last element of the given array and returning it. + ```js const last = arr => arr[arr.length - 1]; ``` @@ -1828,34 +1829,34 @@ const last = arr => arr[arr.length - 1]; ```js last([1, 2, 3]); // 3 -``` +```
[⬆ Back to top](#contents) -### longestItem - -Takes any number of iterable objects or objects with a `length` property and returns the longest one. -If multiple objects have the same length, the first one will be returned. -Returns `undefined` if no arguments are provided. - -Use `Array.prototype.reduce()`, comparing the `length` of objects to find the longest one. - +### longestItem + +Takes any number of iterable objects or objects with a `length` property and returns the longest one. +If multiple objects have the same length, the first one will be returned. +Returns `undefined` if no arguments are provided. + +Use `Array.prototype.reduce()`, comparing the `length` of objects to find the longest one. + ```js -const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a)); +const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a)); ```
Examples ```js -longestItem('this', 'is', 'a', 'testcase'); // 'testcase' -longestItem(...['a', 'ab', 'abc']); // 'abc' -longestItem(...['a', 'ab', 'abc'], 'abcd'); // 'abcd' -longestItem([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]); // [1, 2, 3, 4, 5] -longestItem([1, 2, 3], 'foobar'); // 'foobar' -``` +longestItem('this', 'is', 'a', 'testcase'); // 'testcase' +longestItem(...['a', 'ab', 'abc']); // 'abc' +longestItem(...['a', 'ab', 'abc'], 'abcd'); // 'abcd' +longestItem([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]); // [1, 2, 3, 4, 5] +longestItem([1, 2, 3], 'foobar'); // 'foobar' +```
@@ -1886,15 +1887,15 @@ squareIt([1, 2, 3]); // { 1: 1, 2: 4, 3: 9 }
[⬆ Back to top](#contents) -### maxN - -Returns the `n` maximum elements from the provided array. -If `n` is greater than or equal to the provided array's length, then return the original array (sorted in descending order). - -Use `Array.prototype.sort()` combined with the spread operator (`...`) to create a shallow clone of the array and sort it in descending order. -Use `Array.prototype.slice()` to get the specified number of elements. -Omit the second argument, `n`, to get a one-element array. - +### maxN + +Returns the `n` maximum elements from the provided array. +If `n` is greater than or equal to the provided array's length, then return the original array (sorted in descending order). + +Use `Array.prototype.sort()` combined with the spread operator (`...`) to create a shallow clone of the array and sort it in descending order. +Use `Array.prototype.slice()` to get the specified number of elements. +Omit the second argument, `n`, to get a one-element array. + ```js const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); ``` @@ -1905,21 +1906,21 @@ const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); ```js maxN([1, 2, 3]); // [3] maxN([1, 2, 3], 2); // [3,2] -``` +```
[⬆ Back to top](#contents) -### minN - -Returns the `n` minimum elements from the provided array. -If `n` is greater than or equal to the provided array's length, then return the original array (sorted in ascending order). - -Use `Array.prototype.sort()` combined with the spread operator (`...`) to create a shallow clone of the array and sort it in ascending order. -Use `Array.prototype.slice()` to get the specified number of elements. -Omit the second argument, `n`, to get a one-element array. - +### minN + +Returns the `n` minimum elements from the provided array. +If `n` is greater than or equal to the provided array's length, then return the original array (sorted in ascending order). + +Use `Array.prototype.sort()` combined with the spread operator (`...`) to create a shallow clone of the array and sort it in ascending order. +Use `Array.prototype.slice()` to get the specified number of elements. +Omit the second argument, `n`, to get a one-element array. + ```js const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); ``` @@ -1930,19 +1931,19 @@ const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); ```js minN([1, 2, 3]); // [1] minN([1, 2, 3], 2); // [1,2] -``` +```
[⬆ Back to top](#contents) -### none - -Returns `true` if the provided predicate function returns `false` for all elements in a collection, `false` otherwise. - -Use `Array.prototype.some()` to test if any elements in the collection return `true` based on `fn`. -Omit the second argument, `fn`, to use `Boolean` as a default. - +### none + +Returns `true` if the provided predicate function returns `false` for all elements in a collection, `false` otherwise. + +Use `Array.prototype.some()` to test if any elements in the collection return `true` based on `fn`. +Omit the second argument, `fn`, to use `Boolean` as a default. + ```js const none = (arr, fn = Boolean) => !arr.some(fn); ``` @@ -1953,20 +1954,20 @@ const none = (arr, fn = Boolean) => !arr.some(fn); ```js none([0, 1, 3, 0], x => x == 2); // true none([0, 0, 0]); // true -``` +```
[⬆ Back to top](#contents) -### nthElement - -Returns the nth element of an array. - -Use `Array.prototype.slice()` to get an array containing the nth element at the first place. -If the index is out of bounds, return `undefined`. -Omit the second argument, `n`, to get the first element of the array. - +### nthElement + +Returns the nth element of an array. + +Use `Array.prototype.slice()` to get an array containing the nth element at the first place. +If the index is out of bounds, return `undefined`. +Omit the second argument, `n`, to get the first element of the array. + ```js const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; ``` @@ -1977,20 +1978,20 @@ const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1 ```js nthElement(['a', 'b', 'c'], 1); // 'b' nthElement(['a', 'b', 'b'], -3); // 'a' -``` +```
[⬆ Back to top](#contents) -### offset - -Moves the specified amount of elements to the end of the array. - -Use `Array.prototype.slice()` twice to get the elements after the specified index and the elements before that. -Use the spread operator(`...`) to combine the two into one array. -If `offset` is negative, the elements will be moved from end to start. - +### offset + +Moves the specified amount of elements to the end of the array. + +Use `Array.prototype.slice()` twice to get the elements after the specified index and the elements before that. +Use the spread operator(`...`) to combine the two into one array. +If `offset` is negative, the elements will be moved from end to start. + ```js const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; ``` @@ -2001,19 +2002,19 @@ const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; ```js offset([1, 2, 3, 4, 5], 2); // [3, 4, 5, 1, 2] offset([1, 2, 3, 4, 5], -2); // [4, 5, 1, 2, 3] -``` +```
[⬆ Back to top](#contents) -### partition - -Groups the elements into two arrays, depending on the provided function's truthiness for each element. - -Use `Array.prototype.reduce()` to create an array of two arrays. -Use `Array.prototype.push()` to add elements for which `fn` returns `true` to the first array and elements for which `fn` returns `false` to the second one. - +### partition + +Groups the elements into two arrays, depending on the provided function's truthiness for each element. + +Use `Array.prototype.reduce()` to create an array of two arrays. +Use `Array.prototype.push()` to add elements for which `fn` returns `true` to the first array and elements for which `fn` returns `false` to the second one. + ```js const partition = (arr, fn) => arr.reduce( @@ -2031,7 +2032,7 @@ const partition = (arr, fn) => ```js const users = [{ user: 'barney', age: 36, active: false }, { user: 'fred', age: 40, active: true }]; partition(users, o => o.active); // [[{ 'user': 'fred', 'age': 40, 'active': true }],[{ 'user': 'barney', 'age': 36, 'active': false }]] -``` +``` @@ -2072,15 +2073,15 @@ permutations([1, 33, 5]); // [ [ 1, 33, 5 ], [ 1, 5, 33 ], [ 33, 1, 5 ], [ 33, 5
[⬆ Back to top](#contents) -### pull - -Mutates the original array to filter out the values specified. - -Use `Array.prototype.filter()` and `Array.prototype.includes()` to pull out the values that are not needed. -Use `Array.prototype.length = 0` to mutate the passed in an array by resetting it's length to zero and `Array.prototype.push()` to re-populate it with only the pulled values. - -_(For a snippet that does not mutate the original array see [`without`](#without))_ - +### pull + +Mutates the original array to filter out the values specified. + +Use `Array.prototype.filter()` and `Array.prototype.includes()` to pull out the values that are not needed. +Use `Array.prototype.length = 0` to mutate the passed in an array by resetting it's length to zero and `Array.prototype.push()` to re-populate it with only the pulled values. + +_(For a snippet that does not mutate the original array see [`without`](#without))_ + ```js const pull = (arr, ...args) => { let argState = Array.isArray(args[0]) ? args[0] : args; @@ -2096,7 +2097,7 @@ const pull = (arr, ...args) => { ```js let myArray = ['a', 'b', 'c', 'a', 'b', 'c']; pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ] -``` +``` @@ -2198,13 +2199,13 @@ pullBy(myArray, [{ x: 1 }, { x: 3 }], o => o.x); // myArray = [{ x: 2 }]
[⬆ Back to top](#contents) -### reducedFilter - -Filter an array of objects based on a condition while also filtering out unspecified keys. - -Use `Array.prototype.filter()` to filter the array based on the predicate `fn` so that it returns the objects for which the condition returned a truthy value. -On the filtered array, use `Array.prototype.map()` to return the new object using `Array.prototype.reduce()` to filter out the keys which were not supplied as the `keys` argument. - +### reducedFilter + +Filter an array of objects based on a condition while also filtering out unspecified keys. + +Use `Array.prototype.filter()` to filter the array based on the predicate `fn` so that it returns the objects for which the condition returned a truthy value. +On the filtered array, use `Array.prototype.map()` to return the new object using `Array.prototype.reduce()` to filter out the keys which were not supplied as the `keys` argument. + ```js const reducedFilter = (data, keys, fn) => data.filter(fn).map(el => @@ -2233,18 +2234,18 @@ const data = [ ]; reducedFilter(data, ['id', 'name'], item => item.age > 24); // [{ id: 2, name: 'mike'}] -``` +```
[⬆ Back to top](#contents) -### reduceSuccessive - -Applies a function against an accumulator and each element in the array (from left to right), returning an array of successively reduced values. - -Use `Array.prototype.reduce()` to apply the given function to the given array, storing each new result. - +### reduceSuccessive + +Applies a function against an accumulator and each element in the array (from left to right), returning an array of successively reduced values. + +Use `Array.prototype.reduce()` to apply the given function to the given array, storing each new result. + ```js const reduceSuccessive = (arr, fn, acc) => arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); @@ -2255,19 +2256,19 @@ const reduceSuccessive = (arr, fn, acc) => ```js reduceSuccessive([1, 2, 3, 4, 5, 6], (acc, val) => acc + val, 0); // [0, 1, 3, 6, 10, 15, 21] -``` +```
[⬆ Back to top](#contents) -### reduceWhich - -Returns the minimum/maximum value of an array, after applying the provided function to set comparing rule. - -Use `Array.prototype.reduce()` in combination with the `comparator` function to get the appropriate element in the array. -You can omit the second parameter, `comparator`, to use the default one that returns the minimum element in the array. - +### reduceWhich + +Returns the minimum/maximum value of an array, after applying the provided function to set comparing rule. + +Use `Array.prototype.reduce()` in combination with the `comparator` function to get the appropriate element in the array. +You can omit the second parameter, `comparator`, to use the default one that returns the minimum element in the array. + ```js const reduceWhich = (arr, comparator = (a, b) => a - b) => arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); @@ -2283,16 +2284,16 @@ reduceWhich( [{ name: 'Tom', age: 12 }, { name: 'Jack', age: 18 }, { name: 'Lucy', age: 9 }], (a, b) => a.age - b.age ); // {name: "Lucy", age: 9} -``` +```
[⬆ Back to top](#contents) -### reject - -Takes a predicate and array, like `Array.prototype.filter()`, but only keeps `x` if `pred(x) === false`. - +### reject + +Takes a predicate and array, like `Array.prototype.filter()`, but only keeps `x` if `pred(x) === false`. + ```js const reject = (pred, array) => array.filter((...args) => !pred(...args)); ``` @@ -2303,71 +2304,71 @@ const reject = (pred, array) => array.filter((...args) => !pred(...args)); ```js reject(x => x % 2 === 0, [1, 2, 3, 4, 5]); // [1, 3, 5] reject(word => word.length > 4, ['Apple', 'Pear', 'Kiwi', 'Banana']); // ['Pear', 'Kiwi'] -``` +```
[⬆ Back to top](#contents) -### remove +### remove + +Removes elements from an array for which the given function returns `false`. + +Use `Array.prototype.filter()` to find array elements that return truthy values and `Array.prototype.reduce()` to remove elements using `Array.prototype.splice()`. +The `func` is invoked with three arguments (`value, index, array`). + +```js + +const remove = (arr, func) => + Array.isArray(arr) + ? arr.filter(func).reduce((acc, val) => { + arr.splice(arr.indexOf(val), 1); + return acc.concat(val); + }, []) + : []; +``` -Removes elements from an array for which the given function returns `false`. +
+Examples -Use `Array.prototype.filter()` to find array elements that return truthy values and `Array.prototype.reduce()` to remove elements using `Array.prototype.splice()`. -The `func` is invoked with three arguments (`value, index, array`). +```js +remove([1, 2, 3, 4], n => n % 2 === 0); // [2, 4] +``` +
+ +
[⬆ Back to top](#contents) + +### sample + +Returns a random element from an array. + +Use `Math.random()` to generate a random number, multiply it by `length` and round it off to the nearest whole number using `Math.floor()`. +This method also works with strings. + ```js - -const remove = (arr, func) => - Array.isArray(arr) - ? arr.filter(func).reduce((acc, val) => { - arr.splice(arr.indexOf(val), 1); - return acc.concat(val); - }, []) - : []; +const sample = arr => arr[Math.floor(Math.random() * arr.length)]; ```
Examples ```js -remove([1, 2, 3, 4], n => n % 2 === 0); // [2, 4] -``` +sample([3, 7, 9, 11]); // 9 +```

[⬆ Back to top](#contents) -### sample - -Returns a random element from an array. - -Use `Math.random()` to generate a random number, multiply it by `length` and round it off to the nearest whole number using `Math.floor()`. -This method also works with strings. - -```js -const sample = arr => arr[Math.floor(Math.random() * arr.length)]; -``` - -
-Examples - -```js -sample([3, 7, 9, 11]); // 9 -``` - -
- -
[⬆ Back to top](#contents) - -### sampleSize - -Gets `n` random elements at unique keys from `array` up to the size of `array`. - -Shuffle the array using the [Fisher-Yates algorithm](https://github.com/30-seconds/30-seconds-of-code#shuffle). -Use `Array.prototype.slice()` to get the first `n` elements. -Omit the second argument, `n` to get only one element at random from the array. - +### sampleSize + +Gets `n` random elements at unique keys from `array` up to the size of `array`. + +Shuffle the array using the [Fisher-Yates algorithm](https://github.com/30-seconds/30-seconds-of-code#shuffle). +Use `Array.prototype.slice()` to get the first `n` elements. +Omit the second argument, `n` to get only one element at random from the array. + ```js const sampleSize = ([...arr], n = 1) => { let m = arr.length; @@ -2385,49 +2386,49 @@ const sampleSize = ([...arr], n = 1) => { ```js sampleSize([1, 2, 3], 2); // [3,1] sampleSize([1, 2, 3], 4); // [2,3,1] -``` +```
[⬆ Back to top](#contents) -### shank - -Has the same functionality as [`Array.prototype.splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice), but returning a new array instead of mutating the original array. - -Use `Array.prototype.slice()` and `Array.prototype.concat()` to get a new array with the new contents after removing existing elements and/or adding new elements. -Omit the second argument, `index`, to start at `0`. -Omit the third argument, `delCount`, to remove `0` elements. -Omit the fourth argument, `elements`, in order to not add any new elements. - +### shank + +Has the same functionality as [`Array.prototype.splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice), but returning a new array instead of mutating the original array. + +Use `Array.prototype.slice()` and `Array.prototype.concat()` to get a new array with the new contents after removing existing elements and/or adding new elements. +Omit the second argument, `index`, to start at `0`. +Omit the third argument, `delCount`, to remove `0` elements. +Omit the fourth argument, `elements`, in order to not add any new elements. + ```js -const shank = (arr, index = 0, delCount = 0, ...elements) => - arr - .slice(0, index) - .concat(elements) - .concat(arr.slice(index + delCount)); +const shank = (arr, index = 0, delCount = 0, ...elements) => + arr + .slice(0, index) + .concat(elements) + .concat(arr.slice(index + delCount)); ```
Examples ```js -const names = ['alpha', 'bravo', 'charlie']; -const namesAndDelta = shank(names, 1, 0, 'delta'); // [ 'alpha', 'delta', 'bravo', 'charlie' ] -const namesNoBravo = shank(names, 1, 1); // [ 'alpha', 'charlie' ] -console.log(names); // ['alpha', 'bravo', 'charlie'] -``` +const names = ['alpha', 'bravo', 'charlie']; +const namesAndDelta = shank(names, 1, 0, 'delta'); // [ 'alpha', 'delta', 'bravo', 'charlie' ] +const namesNoBravo = shank(names, 1, 1); // [ 'alpha', 'charlie' ] +console.log(names); // ['alpha', 'bravo', 'charlie'] +```

[⬆ Back to top](#contents) -### shuffle - -Randomizes the order of the values of an array, returning a new array. - -Uses the [Fisher-Yates algorithm](https://github.com/30-seconds/30-seconds-of-code#shuffle) to reorder the elements of the array. - +### shuffle + +Randomizes the order of the values of an array, returning a new array. + +Uses the [Fisher-Yates algorithm](https://github.com/30-seconds/30-seconds-of-code#shuffle) to reorder the elements of the array. + ```js const shuffle = ([...arr]) => { let m = arr.length; @@ -2445,18 +2446,18 @@ const shuffle = ([...arr]) => { ```js const foo = [1, 2, 3]; shuffle(foo); // [2, 3, 1], foo = [1, 2, 3] -``` +```
[⬆ Back to top](#contents) -### similarity - -Returns an array of elements that appear in both arrays. - -Use `Array.prototype.filter()` to remove values that are not part of `values`, determined using `Array.prototype.includes()`. - +### similarity + +Returns an array of elements that appear in both arrays. + +Use `Array.prototype.filter()` to remove values that are not part of `values`, determined using `Array.prototype.includes()`. + ```js const similarity = (arr, values) => arr.filter(v => values.includes(v)); ``` @@ -2466,19 +2467,19 @@ const similarity = (arr, values) => arr.filter(v => values.includes(v)); ```js similarity([1, 2, 3], [1, 2, 4]); // [1, 2] -``` +```
[⬆ Back to top](#contents) -### sortedIndex - -Returns the lowest index at which value should be inserted into array in order to maintain its sort order. - -Check if the array is sorted in descending order (loosely). -Use `Array.prototype.findIndex()` to find the appropriate index where the element should be inserted. - +### sortedIndex + +Returns the lowest index at which value should be inserted into array in order to maintain its sort order. + +Check if the array is sorted in descending order (loosely). +Use `Array.prototype.findIndex()` to find the appropriate index where the element should be inserted. + ```js const sortedIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; @@ -2493,19 +2494,19 @@ const sortedIndex = (arr, n) => { ```js sortedIndex([5, 3, 2, 1], 4); // 1 sortedIndex([30, 50], 40); // 1 -``` +```
[⬆ Back to top](#contents) -### sortedIndexBy - -Returns the lowest index at which value should be inserted into array in order to maintain its sort order, based on a provided iterator function. - -Check if the array is sorted in descending order (loosely). -Use `Array.prototype.findIndex()` to find the appropriate index where the element should be inserted, based on the iterator function `fn`. - +### sortedIndexBy + +Returns the lowest index at which value should be inserted into array in order to maintain its sort order, based on a provided iterator function. + +Check if the array is sorted in descending order (loosely). +Use `Array.prototype.findIndex()` to find the appropriate index where the element should be inserted, based on the iterator function `fn`. + ```js const sortedIndexBy = (arr, n, fn) => { const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); @@ -2520,19 +2521,19 @@ const sortedIndexBy = (arr, n, fn) => { ```js sortedIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 0 -``` +```
[⬆ Back to top](#contents) -### sortedLastIndex - -Returns the highest index at which value should be inserted into array in order to maintain its sort order. - -Check if the array is sorted in descending order (loosely). -Use `Array.prototype.reverse()` and `Array.prototype.findIndex()` to find the appropriate last index where the element should be inserted. - +### sortedLastIndex + +Returns the highest index at which value should be inserted into array in order to maintain its sort order. + +Check if the array is sorted in descending order (loosely). +Use `Array.prototype.reverse()` and `Array.prototype.findIndex()` to find the appropriate last index where the element should be inserted. + ```js const sortedLastIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; @@ -2546,20 +2547,20 @@ const sortedLastIndex = (arr, n) => { ```js sortedLastIndex([10, 20, 30, 30, 40], 30); // 4 -``` +```
[⬆ Back to top](#contents) -### sortedLastIndexBy - -Returns the highest index at which value should be inserted into array in order to maintain its sort order, based on a provided iterator function. - -Check if the array is sorted in descending order (loosely). -Use `Array.prototype.map()` to apply the iterator function to all elements of the array. -Use `Array.prototype.reverse()` and `Array.prototype.findIndex()` to find the appropriate last index where the element should be inserted, based on the provided iterator function. - +### sortedLastIndexBy + +Returns the highest index at which value should be inserted into array in order to maintain its sort order, based on a provided iterator function. + +Check if the array is sorted in descending order (loosely). +Use `Array.prototype.map()` to apply the iterator function to all elements of the array. +Use `Array.prototype.reverse()` and `Array.prototype.findIndex()` to find the appropriate last index where the element should be inserted, based on the provided iterator function. + ```js const sortedLastIndexBy = (arr, n, fn) => { const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); @@ -2577,7 +2578,7 @@ const sortedLastIndexBy = (arr, n, fn) => { ```js sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1 -``` +``` @@ -2612,12 +2613,12 @@ const stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[⬆ Back to top](#contents) -### symmetricDifference - -Returns the symmetric difference between two arrays, without filtering out duplicate values. - -Create a `Set` from each array, then use `Array.prototype.filter()` on each of them to only keep values not contained in the other. - +### symmetricDifference + +Returns the symmetric difference between two arrays, without filtering out duplicate values. + +Create a `Set` from each array, then use `Array.prototype.filter()` on each of them to only keep values not contained in the other. + ```js const symmetricDifference = (a, b) => { const sA = new Set(a), @@ -2632,18 +2633,18 @@ const symmetricDifference = (a, b) => { ```js symmetricDifference([1, 2, 3], [1, 2, 4]); // [3, 4] symmetricDifference([1, 2, 2], [1, 3, 1]); // [2, 2, 3] -``` +```
[⬆ Back to top](#contents) -### symmetricDifferenceBy - -Returns the symmetric difference between two arrays, after applying the provided function to each array element of both. - -Create a `Set` by applying `fn` to each array's elements, then use `Array.prototype.filter()` on each of them to only keep values not contained in the other. - +### symmetricDifferenceBy + +Returns the symmetric difference between two arrays, after applying the provided function to each array element of both. + +Create a `Set` by applying `fn` to each array's elements, then use `Array.prototype.filter()` on each of them to only keep values not contained in the other. + ```js const symmetricDifferenceBy = (a, b, fn) => { const sA = new Set(a.map(v => fn(v))), @@ -2657,18 +2658,18 @@ const symmetricDifferenceBy = (a, b, fn) => { ```js symmetricDifferenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [ 1.2, 3.4 ] -``` +```
[⬆ Back to top](#contents) -### symmetricDifferenceWith - -Returns the symmetric difference between two arrays, using a provided function as a comparator. - -Use `Array.prototype.filter()` and `Array.prototype.findIndex()` to find the appropriate values. - +### symmetricDifferenceWith + +Returns the symmetric difference between two arrays, using a provided function as a comparator. + +Use `Array.prototype.filter()` and `Array.prototype.findIndex()` to find the appropriate values. + ```js const symmetricDifferenceWith = (arr, val, comp) => [ ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), @@ -2685,18 +2686,18 @@ symmetricDifferenceWith( [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b) ); // [1, 1.2, 3.9] -``` +```
[⬆ Back to top](#contents) -### tail - -Returns all elements in an array except for the first one. - -Return `Array.prototype.slice(1)` if the array's `length` is more than `1`, otherwise, return the whole array. - +### tail + +Returns all elements in an array except for the first one. + +Return `Array.prototype.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); ``` @@ -2707,18 +2708,18 @@ const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); ```js tail([1, 2, 3]); // [2,3] tail([1]); // [1] -``` +```
[⬆ Back to top](#contents) -### take - -Returns an array with n elements removed from the beginning. - -Use `Array.prototype.slice()` to create a slice of the array with `n` elements taken from the beginning. - +### take + +Returns an array with n elements removed from the beginning. + +Use `Array.prototype.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); ``` @@ -2729,18 +2730,18 @@ const take = (arr, n = 1) => arr.slice(0, n); ```js take([1, 2, 3], 5); // [1, 2, 3] take([1, 2, 3], 0); // [] -``` +```
[⬆ Back to top](#contents) -### takeRight - -Returns an array with n elements removed from the end. - -Use `Array.prototype.slice()` to create a slice of the array with `n` elements taken from the end. - +### takeRight + +Returns an array with n elements removed from the end. + +Use `Array.prototype.slice()` to create a slice of the array with `n` elements taken from the end. + ```js const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); ``` @@ -2751,41 +2752,41 @@ const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); ```js takeRight([1, 2, 3], 2); // [ 2, 3 ] takeRight([1, 2, 3]); // [3] -``` +```
[⬆ Back to top](#contents) -### takeRightWhile - -Removes elements from the end of an array until the passed function returns `true`. Returns the removed elements. - -Loop through the array, using a `Array.prototype.reduceRight()` and accumulating elements while the function returns falsy value. - +### takeRightWhile + +Removes elements from the end of an array until the passed function returns `true`. Returns the removed elements. + +Loop through the array, using a `Array.prototype.reduceRight()` and accumulating elements while the function returns falsy value. + ```js -const takeRightWhile = (arr, func) => - arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); +const takeRightWhile = (arr, func) => + arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); ```
Examples ```js -takeRightWhile([1, 2, 3, 4], n => n < 3); // [3, 4] -``` +takeRightWhile([1, 2, 3, 4], n => n < 3); // [3, 4] +```

[⬆ Back to top](#contents) -### takeWhile - -Removes elements in an array until the passed function returns `true`. Returns the removed elements. - -Loop through the array, using a `for...of` loop over `Array.prototype.entries()` until the returned value from the function is `true`. -Return the removed elements, using `Array.prototype.slice()`. - +### takeWhile + +Removes elements in an array until the passed function returns `true`. Returns the removed elements. + +Loop through the array, using a `for...of` loop over `Array.prototype.entries()` until the returned value from the function is `true`. +Return the removed elements, using `Array.prototype.slice()`. + ```js const takeWhile = (arr, func) => { for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); @@ -2798,56 +2799,56 @@ const takeWhile = (arr, func) => { ```js takeWhile([1, 2, 3, 4], n => n >= 3); // [1, 2] -``` +```
[⬆ Back to top](#contents) -### toHash - -Reduces a given Array-like into a value hash (keyed data store). - -Given an Iterable or Array-like structure, call `Array.prototype.reduce.call()` on the provided object to step over it and return an Object, keyed by the reference value. - +### toHash + +Reduces a given Array-like into a value hash (keyed data store). + +Given an Iterable or Array-like structure, call `Array.prototype.reduce.call()` on the provided object to step over it and return an Object, keyed by the reference value. + ```js -const toHash = (object, key) => - Array.prototype.reduce.call( - object, - (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), - {} - ); +const toHash = (object, key) => + Array.prototype.reduce.call( + object, + (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), + {} + ); ```
Examples ```js -toHash([4, 3, 2, 1]); // { 0: 4, 1: 3, 2: 2, 3: 1 } -toHash([{ a: 'label' }], 'a'); // { label: { a: 'label' } } -// A more in depth example: -let users = [{ id: 1, first: 'Jon' }, { id: 2, first: 'Joe' }, { id: 3, first: 'Moe' }]; -let managers = [{ manager: 1, employees: [2, 3] }]; -// We use function here because we want a bindable reference, but a closure referencing the hash would work, too. -managers.forEach( - manager => - (manager.employees = manager.employees.map(function(id) { - return this[id]; - }, toHash(users, 'id'))) -); -managers; // [ { manager:1, employees: [ { id: 2, first: "Joe" }, { id: 3, first: "Moe" } ] } ] -``` +toHash([4, 3, 2, 1]); // { 0: 4, 1: 3, 2: 2, 3: 1 } +toHash([{ a: 'label' }], 'a'); // { label: { a: 'label' } } +// A more in depth example: +let users = [{ id: 1, first: 'Jon' }, { id: 2, first: 'Joe' }, { id: 3, first: 'Moe' }]; +let managers = [{ manager: 1, employees: [2, 3] }]; +// We use function here because we want a bindable reference, but a closure referencing the hash would work, too. +managers.forEach( + manager => + (manager.employees = manager.employees.map(function(id) { + return this[id]; + }, toHash(users, 'id'))) +); +managers; // [ { manager:1, employees: [ { id: 2, first: "Joe" }, { id: 3, first: "Moe" } ] } ] +```

[⬆ Back to top](#contents) -### union - -Returns every element that exists in any of the two arrays once. - -Create a `Set` with all values of `a` and `b` and convert to an array. - +### union + +Returns every element that exists in any of the two arrays once. + +Create a `Set` with all values of `a` and `b` and convert to an array. + ```js const union = (a, b) => Array.from(new Set([...a, ...b])); ``` @@ -2857,44 +2858,44 @@ const union = (a, b) => Array.from(new Set([...a, ...b])); ```js union([1, 2, 3], [4, 3, 2]); // [1,2,3,4] -``` +```
[⬆ Back to top](#contents) -### unionBy - -Returns every element that exists in any of the two arrays once, after applying the provided function to each array element of both. - -Create a `Set` by applying all `fn` to all values of `a`. -Create a `Set` from `a` and all elements in `b` whose value, after applying `fn` does not match a value in the previously created set. -Return the last set converted to an array. - +### unionBy + +Returns every element that exists in any of the two arrays once, after applying the provided function to each array element of both. + +Create a `Set` by applying all `fn` to all values of `a`. +Create a `Set` from `a` and all elements in `b` whose value, after applying `fn` does not match a value in the previously created set. +Return the last set converted to an array. + ```js -const unionBy = (a, b, fn) => { - const s = new Set(a.map(fn)); - return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); -}; +const unionBy = (a, b, fn) => { + const s = new Set(a.map(fn)); + return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); +}; ```
Examples ```js -unionBy([2.1], [1.2, 2.3], Math.floor); // [2.1, 1.2] -``` +unionBy([2.1], [1.2, 2.3], Math.floor); // [2.1, 1.2] +```

[⬆ Back to top](#contents) -### unionWith - -Returns every element that exists in any of the two arrays once, using a provided comparator function. - -Create a `Set` with all values of `a` and values in `b` for which the comparator finds no matches in `a`, using `Array.prototype.findIndex()`. - +### unionWith + +Returns every element that exists in any of the two arrays once, using a provided comparator function. + +Create a `Set` with all values of `a` and values in `b` for which the comparator finds no matches in `a`, using `Array.prototype.findIndex()`. + ```js const unionWith = (a, b, comp) => Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); @@ -2905,18 +2906,18 @@ const unionWith = (a, b, comp) => ```js unionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2, 1.5, 3, 0, 3.9] -``` +```
[⬆ Back to top](#contents) -### uniqueElements - -Returns all unique values of an array. - -Use ES6 `Set` and the `...rest` operator to discard all duplicated values. - +### uniqueElements + +Returns all unique values of an array. + +Use ES6 `Set` and the `...rest` operator to discard all duplicated values. + ```js const uniqueElements = arr => [...new Set(arr)]; ``` @@ -2926,19 +2927,19 @@ const uniqueElements = arr => [...new Set(arr)]; ```js uniqueElements([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5] -``` +```
[⬆ Back to top](#contents) -### uniqueElementsBy - -Returns all unique values of an array, based on a provided comparator function. - -Use `Array.prototype.reduce()` and `Array.prototype.some()` for an array containing only the first unique occurence of each value, based on the comparator function, `fn`. -The comparator function takes two arguments: the values of the two elements being compared. - +### uniqueElementsBy + +Returns all unique values of an array, based on a provided comparator function. + +Use `Array.prototype.reduce()` and `Array.prototype.some()` for an array containing only the first unique occurence of each value, based on the comparator function, `fn`. +The comparator function takes two arguments: the values of the two elements being compared. + ```js const uniqueElementsBy = (arr, fn) => arr.reduce((acc, v) => { @@ -2961,19 +2962,19 @@ uniqueElementsBy( ], (a, b) => a.id == b.id ); // [ { id: 0, value: 'a' }, { id: 1, value: 'b' }, { id: 2, value: 'c' } ] -``` +```
[⬆ Back to top](#contents) -### uniqueElementsByRight - -Returns all unique values of an array, based on a provided comparator function. - -Use `Array.prototype.reduce()` and `Array.prototype.some()` for an array containing only the last unique occurence of each value, based on the comparator function, `fn`. -The comparator function takes two arguments: the values of the two elements being compared. - +### uniqueElementsByRight + +Returns all unique values of an array, based on a provided comparator function. + +Use `Array.prototype.reduce()` and `Array.prototype.some()` for an array containing only the last unique occurence of each value, based on the comparator function, `fn`. +The comparator function takes two arguments: the values of the two elements being compared. + ```js const uniqueElementsByRight = (arr, fn) => arr.reduceRight((acc, v) => { @@ -2996,18 +2997,18 @@ uniqueElementsByRight( ], (a, b) => a.id == b.id ); // [ { id: 0, value: 'e' }, { id: 1, value: 'd' }, { id: 2, value: 'c' } ] -``` +```
[⬆ Back to top](#contents) -### uniqueSymmetricDifference - -Returns the unique symmetric difference between two arrays, not containing duplicate values from either array. - -Use `Array.prototype.filter()` and `Array.prototype.includes()` on each array to remove values contained in the other, then create a `Set` from the results, removing duplicate values. - +### uniqueSymmetricDifference + +Returns the unique symmetric difference between two arrays, not containing duplicate values from either array. + +Use `Array.prototype.filter()` and `Array.prototype.includes()` on each array to remove values contained in the other, then create a `Set` from the results, removing duplicate values. + ```js const uniqueSymmetricDifference = (a, b) => [ ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) @@ -3020,36 +3021,36 @@ const uniqueSymmetricDifference = (a, b) => [ ```js uniqueSymmetricDifference([1, 2, 3], [1, 2, 4]); // [3, 4] uniqueSymmetricDifference([1, 2, 2], [1, 3, 1]); // [2, 3] -``` +```
[⬆ Back to top](#contents) -### unzip - -Creates an array of arrays, ungrouping the elements in an array produced by [zip](#zip). - -Use `Math.max.apply()` to get the longest subarray in the array, `Array.prototype.map()` to make each element an array. -Use `Array.prototype.reduce()` and `Array.prototype.forEach()` to map grouped values to individual arrays. - +### unzip + +Creates an array of arrays, ungrouping the elements in an array produced by [zip](#zip). + +Use `Math.max.apply()` to get the longest subarray in the array, `Array.prototype.map()` to make each element an array. +Use `Array.prototype.reduce()` and `Array.prototype.forEach()` to map grouped values to individual arrays. + ```js -const unzip = arr => - arr.reduce( - (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), - Array.from({ - length: Math.max(...arr.map(x => x.length)) - }).map(x => []) - ); +const unzip = arr => + arr.reduce( + (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), + Array.from({ + length: Math.max(...arr.map(x => x.length)) + }).map(x => []) + ); ```
Examples ```js -unzip([['a', 1, true], ['b', 2, false]]); // [['a', 'b'], [1, 2], [true, false]] -unzip([['a', 1, true], ['b', 2]]); // [['a', 'b'], [1, 2], [true]] -``` +unzip([['a', 1, true], ['b', 2, false]]); // [['a', 'b'], [1, 2], [true, false]] +unzip([['a', 1, true], ['b', 2]]); // [['a', 'b'], [1, 2], [true]] +```
@@ -3086,14 +3087,14 @@ unzipWith([[1, 10, 100], [2, 20, 200]], (...args) => args.reduce((acc, v) => acc
[⬆ Back to top](#contents) -### without - -Filters out the elements of an array, that have one of the specified values. - -Use `Array.prototype.filter()` to create an array excluding(using `!Array.includes()`) all given values. - -_(For a snippet that mutates the original array see [`pull`](#pull))_ - +### without + +Filters out the elements of an array, that have one of the specified values. + +Use `Array.prototype.filter()` to create an array excluding(using `!Array.includes()`) all given values. + +_(For a snippet that mutates the original array see [`pull`](#pull))_ + ```js const without = (arr, ...args) => arr.filter(v => !args.includes(v)); ``` @@ -3103,18 +3104,18 @@ const without = (arr, ...args) => arr.filter(v => !args.includes(v)); ```js without([2, 1, 2, 3], 1, 2); // [3] -``` +```
[⬆ Back to top](#contents) -### xProd - -Creates a new array out of the two supplied by creating each possible pair from the arrays. - -Use `Array.prototype.reduce()`, `Array.prototype.map()` and `Array.prototype.concat()` to produce every possible pair from the elements of the two arrays and save them in an array. - +### xProd + +Creates a new array out of the two supplied by creating each possible pair from the arrays. + +Use `Array.prototype.reduce()`, `Array.prototype.map()` and `Array.prototype.concat()` to produce every possible pair from the elements of the two arrays and save them in an array. + ```js const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); ``` @@ -3124,20 +3125,20 @@ const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []) ```js xProd([1, 2], ['a', 'b']); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']] -``` +```
[⬆ Back to top](#contents) -### zip - -Creates an array of elements, grouped based on the position in the original arrays. - -Use `Math.max.apply()` to get the longest array in the arguments. -Creates an array with that length as return value and use `Array.from()` with a map-function to create an array of grouped elements. -If lengths of the argument-arrays vary, `undefined` is used where no value could be found. - +### zip + +Creates an array of elements, grouped based on the position in the original arrays. + +Use `Math.max.apply()` to get the longest array in the arguments. +Creates an array with that length as return value and use `Array.from()` with a map-function to create an array of grouped elements. +If lengths of the argument-arrays vary, `undefined` is used where no value could be found. + ```js const zip = (...arrays) => { const maxLength = Math.max(...arrays.map(x => x.length)); @@ -3153,18 +3154,18 @@ const zip = (...arrays) => { ```js zip(['a', 'b'], [1, 2], [true, false]); // [['a', 1, true], ['b', 2, false]] zip(['a'], [1, 2], [true, false]); // [['a', 1, true], [undefined, 2, false]] -``` +```
[⬆ Back to top](#contents) -### zipObject - -Given an array of valid property identifiers and an array of values, return an object associating the properties to the values. - -Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using `Array.prototype.reduce()`. - +### zipObject + +Given an array of valid property identifiers and an array of values, return an object associating the properties to the values. + +Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using `Array.prototype.reduce()`. + ```js const zipObject = (props, values) => props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); @@ -3176,7 +3177,7 @@ const zipObject = (props, values) => ```js zipObject(['a', 'b', 'c'], [1, 2]); // {a: 1, b: 2, c: undefined} zipObject(['a', 'b'], [1, 2, 3]); // {a: 1, b: 2} -``` +``` @@ -3224,12 +3225,12 @@ zipWith( ## 🌐 Browser -### arrayToHtmlList - -Converts the given array elements into `
  • ` tags and appends them to the list of the given id. - -Use `Array.prototype.map()`, `document.querySelector()`, and an anonymous inner closure to create a list of html tags. - +### arrayToHtmlList + +Converts the given array elements into `
  • ` tags and appends them to the list of the given id. + +Use `Array.prototype.map()`, `document.querySelector()`, and an anonymous inner closure to create a list of html tags. + ```js const arrayToHtmlList = (arr, listID) => (el => ( @@ -3243,18 +3244,18 @@ const arrayToHtmlList = (arr, listID) => ```js arrayToHtmlList(['item 1', 'item 2'], 'myListID'); -``` +```
    [⬆ Back to top](#contents) -### bottomVisible - -Returns `true` if the bottom of the page is visible, `false` otherwise. - -Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. - +### bottomVisible + +Returns `true` if the bottom of the page is visible, `false` otherwise. + +Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. + ```js const bottomVisible = () => document.documentElement.clientHeight + window.scrollY >= @@ -3266,7 +3267,7 @@ const bottomVisible = () => ```js bottomVisible(); // true -``` +``` @@ -3351,15 +3352,15 @@ counter('#my-id', 1, 1000, 5, 2000); // Creates a 2-second timer for the element
    [⬆ Back to top](#contents) -### createElement - -Creates an element from a string (without appending it to the document). -If the given string contains multiple elements, only the first one will be returned. - -Use `document.createElement()` to create a new element. -Set its `innerHTML` to the string supplied as the argument. -Use `ParentNode.firstElementChild` to return the element version of the string. - +### createElement + +Creates an element from a string (without appending it to the document). +If the given string contains multiple elements, only the first one will be returned. + +Use `document.createElement()` to create a new element. +Set its `innerHTML` to the string supplied as the argument. +Use `ParentNode.firstElementChild` to return the element version of the string. + ```js const createElement = str => { const el = document.createElement('div'); @@ -3378,7 +3379,7 @@ const el = createElement( ` ); console.log(el.className); // 'container' -``` +``` @@ -3437,12 +3438,12 @@ hub.off('message', handler);
    [⬆ Back to top](#contents) -### currentURL - -Returns the current URL. - -Use `window.location.href` to get current URL. - +### currentURL + +Returns the current URL. + +Use `window.location.href` to get current URL. + ```js const currentURL = () => window.location.href; ``` @@ -3452,18 +3453,18 @@ const currentURL = () => window.location.href; ```js currentURL(); // 'https://google.com' -``` +```
    [⬆ Back to top](#contents) -### detectDeviceType - -Detects wether the website is being opened in a mobile device or a desktop/laptop. - -Use a regular expression to test the `navigator.userAgent` property to figure out if the device is a mobile device or a desktop/laptop. - +### detectDeviceType + +Detects wether the website is being opened in a mobile device or a desktop/laptop. + +Use a regular expression to test the `navigator.userAgent` property to figure out if the device is a mobile device or a desktop/laptop. + ```js const detectDeviceType = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) @@ -3476,18 +3477,18 @@ const detectDeviceType = () => ```js detectDeviceType(); // "Mobile" or "Desktop" -``` +```
    [⬆ Back to top](#contents) -### elementContains - -Returns `true` if the `parent` element contains the `child` element, `false` otherwise. - -Check that `parent` is not the same element as `child`, use `parent.contains(child)` to check if the `parent` element contains the `child` element. - +### elementContains + +Returns `true` if the `parent` element contains the `child` element, `false` otherwise. + +Check that `parent` is not the same element as `child`, use `parent.contains(child)` to check if the `parent` element contains the `child` element. + ```js const elementContains = (parent, child) => parent !== child && parent.contains(child); ``` @@ -3498,7 +3499,7 @@ const elementContains = (parent, child) => parent !== child && parent.contains(c ```js elementContains(document.querySelector('head'), document.querySelector('title')); // true elementContains(document.querySelector('body'), document.querySelector('body')); // false -``` +``` @@ -3537,38 +3538,38 @@ elementIsVisibleInViewport(el, true); // true - (partially visible)
    [⬆ Back to top](#contents) -### getImages - -Fetches all images from within an element and puts them into an array - -Use `Element.prototype.getElementsByTagName()` to fetch all `` elements inside the provided element, `Array.prototype.map()` to map every `src` attribute of their respective `` element, then create a `Set` to eliminate duplicates and return the array. - +### getImages + +Fetches all images from within an element and puts them into an array + +Use `Element.prototype.getElementsByTagName()` to fetch all `` elements inside the provided element, `Array.prototype.map()` to map every `src` attribute of their respective `` element, then create a `Set` to eliminate duplicates and return the array. + ```js -const getImages = (el, includeDuplicates = false) => { - const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); - return includeDuplicates ? images : [...new Set(images)]; -}; +const getImages = (el, includeDuplicates = false) => { + const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); + return includeDuplicates ? images : [...new Set(images)]; +}; ```
    Examples ```js -getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...'] -getImages(document, false); // ['image1.jpg', 'image2.png', '...'] -``` +getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...'] +getImages(document, false); // ['image1.jpg', 'image2.png', '...'] +```

    [⬆ Back to top](#contents) -### getScrollPosition - -Returns the scroll position of the current page. - -Use `pageXOffset` and `pageYOffset` if they are defined, otherwise `scrollLeft` and `scrollTop`. -You can omit `el` to use a default value of `window`. - +### getScrollPosition + +Returns the scroll position of the current page. + +Use `pageXOffset` and `pageYOffset` if they are defined, otherwise `scrollLeft` and `scrollTop`. +You can omit `el` to use a default value of `window`. + ```js const getScrollPosition = (el = window) => ({ x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, @@ -3581,18 +3582,18 @@ const getScrollPosition = (el = window) => ({ ```js getScrollPosition(); // {x: 0, y: 200} -``` +```
    [⬆ Back to top](#contents) -### getStyle - -Returns the value of a CSS rule for the specified element. - -Use `Window.getComputedStyle()` to get the value of the CSS rule for the specified element. - +### getStyle + +Returns the value of a CSS rule for the specified element. + +Use `Window.getComputedStyle()` to get the value of the CSS rule for the specified element. + ```js const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; ``` @@ -3602,18 +3603,18 @@ const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; ```js getStyle(document.querySelector('p'), 'font-size'); // '16px' -``` +```
    [⬆ Back to top](#contents) -### hasClass - -Returns `true` if the element has the specified class, `false` otherwise. - -Use `element.classList.contains()` to check if the element has the specified class. - +### hasClass + +Returns `true` if the element has the specified class, `false` otherwise. + +Use `element.classList.contains()` to check if the element has the specified class. + ```js const hasClass = (el, className) => el.classList.contains(className); ``` @@ -3623,7 +3624,7 @@ const hasClass = (el, className) => el.classList.contains(className); ```js hasClass(document.querySelector('p.special'), 'special'); // true -``` +``` @@ -3657,33 +3658,33 @@ hashBrowser(JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })).then
    [⬆ Back to top](#contents) -### hide - -Hides all the elements specified. - -Use `NodeList.prototype.forEach()` to apply `display: none` to each element specified. - +### hide + +Hides all the elements specified. + +Use `NodeList.prototype.forEach()` to apply `display: none` to each element specified. + ```js -const hide = (...el) => [...el].forEach(e => (e.style.display = 'none')); +const hide = (...el) => [...el].forEach(e => (e.style.display = 'none')); ```
    Examples ```js -hide(document.querySelectorAll('img')); // Hides all elements on the page -``` +hide(document.querySelectorAll('img')); // Hides all elements on the page +```

    [⬆ Back to top](#contents) -### httpsRedirect - -Redirects the page to HTTPS if its currently in HTTP. Also, pressing the back button doesn't take it back to the HTTP page as its replaced in the history. - -Use `location.protocol` to get the protocol currently being used. If it's not HTTPS, use `location.replace()` to replace the existing page with the HTTPS version of the page. Use `location.href` to get the full address, split it with `String.prototype.split()` and remove the protocol part of the URL. - +### httpsRedirect + +Redirects the page to HTTPS if its currently in HTTP. Also, pressing the back button doesn't take it back to the HTTP page as its replaced in the history. + +Use `location.protocol` to get the protocol currently being used. If it's not HTTPS, use `location.replace()` to replace the existing page with the HTTPS version of the page. Use `location.href` to get the full address, split it with `String.prototype.split()` and remove the protocol part of the URL. + ```js const httpsRedirect = () => { if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); @@ -3695,18 +3696,18 @@ const httpsRedirect = () => { ```js httpsRedirect(); // If you are on http://mydomain.com, you are redirected to https://mydomain.com -``` +```
    [⬆ Back to top](#contents) -### insertAfter - -Inserts an HTML string after the end of the specified element. - -Use `el.insertAdjacentHTML()` with a position of `'afterend'` to parse `htmlString` and insert it after the end of `el`. - +### insertAfter + +Inserts an HTML string after the end of the specified element. + +Use `el.insertAdjacentHTML()` with a position of `'afterend'` to parse `htmlString` and insert it after the end of `el`. + ```js const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); ``` @@ -3716,18 +3717,18 @@ const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlSt ```js insertAfter(document.getElementById('myId'), '

    after

    '); //
    ...

    after

    -``` +```
    [⬆ Back to top](#contents) -### insertBefore - -Inserts an HTML string before the start of the specified element. - -Use `el.insertAdjacentHTML()` with a position of `'beforebegin'` to parse `htmlString` and insert it before the start of `el`. - +### insertBefore + +Inserts an HTML string before the start of the specified element. + +Use `el.insertAdjacentHTML()` with a position of `'beforebegin'` to parse `htmlString` and insert it before the start of `el`. + ```js const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); ``` @@ -3737,18 +3738,18 @@ const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', ht ```js insertBefore(document.getElementById('myId'), '

    before

    '); //

    before

    ...
    -``` +```
    [⬆ Back to top](#contents) -### isBrowserTabFocused - -Returns `true` if the browser tab of the page is focused, `false` otherwise. - -Use the `Document.hidden` property, introduced by the Page Visibility API to check if the browser tab of the page is visible or hidden. - +### isBrowserTabFocused + +Returns `true` if the browser tab of the page is focused, `false` otherwise. + +Use the `Document.hidden` property, introduced by the Page Visibility API to check if the browser tab of the page is visible or hidden. + ```js const isBrowserTabFocused = () => !document.hidden; ``` @@ -3758,18 +3759,18 @@ const isBrowserTabFocused = () => !document.hidden; ```js isBrowserTabFocused(); // true -``` +```
    [⬆ Back to top](#contents) -### nodeListToArray - -Converts a `NodeList` to an array. - -Use spread operator inside new array to convert a `NodeList` to an array. - +### nodeListToArray + +Converts a `NodeList` to an array. + +Use spread operator inside new array to convert a `NodeList` to an array. + ```js const nodeListToArray = nodeList => [...nodeList]; ``` @@ -3779,7 +3780,7 @@ const nodeListToArray = nodeList => [...nodeList]; ```js nodeListToArray(document.childNodes); // [ , html ] -``` +``` @@ -3826,13 +3827,13 @@ obs.disconnect(); // Disconnects the observer and stops logging mutations on the
    [⬆ Back to top](#contents) -### off - -Removes an event listener from an element. - -Use `EventTarget.removeEventListener()` to remove an event listener from an element. -Omit the fourth argument `opts` to use `false` or specify it based on the options used when the event listener was added. - +### off + +Removes an event listener from an element. + +Use `EventTarget.removeEventListener()` to remove an event listener from an element. +Omit the fourth argument `opts` to use `false` or specify it based on the options used when the event listener was added. + ```js const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); ``` @@ -3844,20 +3845,20 @@ const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts) const fn = () => console.log('!'); document.body.addEventListener('click', fn); off(document.body, 'click', fn); // no longer logs '!' upon clicking on the page -``` +```
    [⬆ Back to top](#contents) -### on - -Adds an event listener to an element with the ability to use event delegation. - -Use `EventTarget.addEventListener()` to add an event listener to an element. If there is a `target` property supplied to the options object, ensure the event target matches the target specified and then invoke the callback by supplying the correct `this` context. -Returns a reference to the custom delegator function, in order to be possible to use with [`off`](#off). -Omit `opts` to default to non-delegation behavior and event bubbling. - +### on + +Adds an event listener to an element with the ability to use event delegation. + +Use `EventTarget.addEventListener()` to add an event listener to an element. If there is a `target` property supplied to the options object, ensure the event target matches the target specified and then invoke the callback by supplying the correct `this` context. +Returns a reference to the custom delegator function, in order to be possible to use with [`off`](#off). +Omit `opts` to default to non-delegation behavior and event bubbling. + ```js const on = (el, evt, fn, opts = {}) => { const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); @@ -3874,7 +3875,7 @@ const fn = () => console.log('!'); on(document.body, 'click', fn); // logs '!' upon clicking the body on(document.body, 'click', fn, { target: 'p' }); // logs '!' upon clicking a `p` element child of the body on(document.body, 'click', fn, { options: true }); // use capturing instead of bubbling -``` +``` @@ -3918,13 +3919,13 @@ onUserInputChange(type => {
    [⬆ Back to top](#contents) -### prefix - -Returns the prefixed version (if necessary) of a CSS property that the browser supports. - -Use `Array.prototype.findIndex()` on an array of vendor prefix strings to test if `document.body` has one of them defined in its `CSSStyleDeclaration` object, otherwise return `null`. -Use `String.prototype.charAt()` and `String.prototype.toUpperCase()` to capitalize the property, which will be appended to the vendor prefix string. - +### prefix + +Returns the prefixed version (if necessary) of a CSS property that the browser supports. + +Use `Array.prototype.findIndex()` on an array of vendor prefix strings to test if `document.body` has one of them defined in its `CSSStyleDeclaration` object, otherwise return `null`. +Use `String.prototype.charAt()` and `String.prototype.toUpperCase()` to capitalize the property, which will be appended to the vendor prefix string. + ```js const prefix = prop => { const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); @@ -3941,21 +3942,21 @@ const prefix = prop => { ```js prefix('appearance'); // 'appearance' on a supported browser, otherwise 'webkitAppearance', 'mozAppearance', 'msAppearance' or 'oAppearance' -``` +```
    [⬆ Back to top](#contents) -### recordAnimationFrames - -Invokes the provided callback on each animation frame. - -Use recursion. -Provided that `running` is `true`, continue invoking `window.requestAnimationFrame()` which invokes the provided callback. -Return an object with two methods `start` and `stop` to allow manual control of the recording. -Omit the second argument, `autoStart`, to implicitly call `start` when the function is invoked. - +### recordAnimationFrames + +Invokes the provided callback on each animation frame. + +Use recursion. +Provided that `running` is `true`, continue invoking `window.requestAnimationFrame()` which invokes the provided callback. +Return an object with two methods `start` and `stop` to allow manual control of the recording. +Omit the second argument, `autoStart`, to implicitly call `start` when the function is invoked. + ```js const recordAnimationFrames = (callback, autoStart = true) => { let running = true, @@ -3988,19 +3989,19 @@ const recorder = recordAnimationFrames(cb); // logs 'Animation frame fired' on e recorder.stop(); // stops logging recorder.start(); // starts again const recorder2 = recordAnimationFrames(cb, false); // `start` needs to be explicitly called to begin recording frames -``` +```
    [⬆ Back to top](#contents) -### redirect - -Redirects to a specified 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`). - +### redirect + +Redirects to a specified 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); @@ -4011,7 +4012,7 @@ const redirect = (url, asLink = true) => ```js redirect('https://google.com'); -``` +``` @@ -4069,13 +4070,13 @@ runAsync(() => typeof outsideVariable).then(console.log); // 'undefined'
    [⬆ Back to top](#contents) -### scrollToTop - -Smooth-scrolls to the top of the page. - -Get distance from top using `document.documentElement.scrollTop` or `document.body.scrollTop`. -Scroll by a fraction of the distance from the top. Use `window.requestAnimationFrame()` to animate the scrolling. - +### scrollToTop + +Smooth-scrolls to the top of the page. + +Get distance from top using `document.documentElement.scrollTop` or `document.body.scrollTop`. +Scroll by a fraction of the distance from the top. Use `window.requestAnimationFrame()` to animate the scrolling. + ```js const scrollToTop = () => { const c = document.documentElement.scrollTop || document.body.scrollTop; @@ -4091,18 +4092,18 @@ const scrollToTop = () => { ```js scrollToTop(); -``` +```
    [⬆ Back to top](#contents) -### setStyle - -Sets the value of a CSS rule for the specified element. - -Use `element.style` to set the value of the CSS rule for the specified element to `val`. - +### setStyle + +Sets the value of a CSS rule for the specified element. + +Use `element.style` to set the value of the CSS rule for the specified element to `val`. + ```js const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); ``` @@ -4112,18 +4113,18 @@ const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); ```js setStyle(document.querySelector('p'), 'font-size', '20px'); // The first

    element on the page will have a font-size of 20px -``` +```
    [⬆ Back to top](#contents) -### show - -Shows all the elements specified. - -Use the spread operator (`...`) and `Array.prototype.forEach()` to clear the `display` property for each element specified. - +### show + +Shows all the elements specified. + +Use the spread operator (`...`) and `Array.prototype.forEach()` to clear the `display` property for each element specified. + ```js const show = (...el) => [...el].forEach(e => (e.style.display = '')); ``` @@ -4133,19 +4134,19 @@ const show = (...el) => [...el].forEach(e => (e.style.display = '')); ```js show(...document.querySelectorAll('img')); // Shows all elements on the page -``` +```
    [⬆ Back to top](#contents) -### smoothScroll - -Smoothly scrolls the element on which it's called into the visible area of the browser window. - -Use `.scrollIntoView` method to scroll the element. -Pass `{ behavior: 'smooth' }` to `.scrollIntoView` so it scrolls smoothly. - +### smoothScroll + +Smoothly scrolls the element on which it's called into the visible area of the browser window. + +Use `.scrollIntoView` method to scroll the element. +Pass `{ behavior: 'smooth' }` to `.scrollIntoView` so it scrolls smoothly. + ```js const smoothScroll = element => document.querySelector(element).scrollIntoView({ @@ -4159,18 +4160,18 @@ const smoothScroll = element => ```js smoothScroll('#fooBar'); // scrolls smoothly to the element with the id fooBar smoothScroll('.fooBar'); // scrolls smoothly to the first element with a class of fooBar -``` +```
    [⬆ Back to top](#contents) -### toggleClass - -Toggle a class for an element. - -Use `element.classList.toggle()` to toggle the specified class for the element. - +### toggleClass + +Toggle a class for an element. + +Use `element.classList.toggle()` to toggle the specified class for the element. + ```js const toggleClass = (el, className) => el.classList.toggle(className); ``` @@ -4180,43 +4181,43 @@ const toggleClass = (el, className) => el.classList.toggle(className); ```js toggleClass(document.querySelector('p.special'), 'special'); // The paragraph will not have the 'special' class anymore -``` +```
    [⬆ Back to top](#contents) -### triggerEvent - -Triggers a specific event on a given element, optionally passing custom data. - -Use `new CustomEvent()` to create an event from the specified `eventType` and details. -Use `el.dispatchEvent()` to trigger the newly created event on the given element. -Omit the third argument, `detail`, if you do not want to pass custom data to the triggered event. - +### triggerEvent + +Triggers a specific event on a given element, optionally passing custom data. + +Use `new CustomEvent()` to create an event from the specified `eventType` and details. +Use `el.dispatchEvent()` to trigger the newly created event on the given element. +Omit the third argument, `detail`, if you do not want to pass custom data to the triggered event. + ```js -const triggerEvent = (el, eventType, detail) => - el.dispatchEvent(new CustomEvent(eventType, { detail })); +const triggerEvent = (el, eventType, detail) => + el.dispatchEvent(new CustomEvent(eventType, { detail })); ```

    Examples ```js -triggerEvent(document.getElementById('myId'), 'click'); -triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' }); -``` +triggerEvent(document.getElementById('myId'), 'click'); +triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' }); +```

    [⬆ Back to top](#contents) -### UUIDGeneratorBrowser - -Generates a UUID in a browser. - -Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4. - +### UUIDGeneratorBrowser + +Generates a UUID in a browser. + +Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4. + ```js const UUIDGeneratorBrowser = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => @@ -4229,7 +4230,7 @@ const UUIDGeneratorBrowser = () => ```js UUIDGeneratorBrowser(); // '7982fcfe-5721-4632-bede-6000885be57d' -``` +``` @@ -4240,38 +4241,38 @@ UUIDGeneratorBrowser(); // '7982fcfe-5721-4632-bede-6000885be57d' ## ⏱️ Date -### dayOfYear - -Gets the day of the year from a `Date` object. - -Use `new Date()` and `Date.prototype.getFullYear()` to get the first day of the year as a `Date` object, subtract it from the provided `date` and divide with the milliseconds in each day to get the result. -Use `Math.floor()` to appropriately round the resulting day count to an integer. - +### dayOfYear + +Gets the day of the year from a `Date` object. + +Use `new Date()` and `Date.prototype.getFullYear()` to get the first day of the year as a `Date` object, subtract it from the provided `date` and divide with the milliseconds in each day to get the result. +Use `Math.floor()` to appropriately round the resulting day count to an integer. + ```js -const dayOfYear = date => - Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); +const dayOfYear = date => + Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); ```
    Examples ```js -dayOfYear(new Date()); // 272 -``` +dayOfYear(new Date()); // 272 +```

    [⬆ Back to top](#contents) -### formatDuration - -Returns the human readable format of the given number of milliseconds. - -Divide `ms` with the appropriate values to obtain the appropriate values for `day`, `hour`, `minute`, `second` and `millisecond`. -Use `Object.entries()` with `Array.prototype.filter()` to keep only non-zero values. -Use `Array.prototype.map()` to create the string for each value, pluralizing appropriately. -Use `String.prototype.join(', ')` to combine the values into a string. - +### formatDuration + +Returns the human readable format of the given number of milliseconds. + +Divide `ms` with the appropriate values to obtain the appropriate values for `day`, `hour`, `minute`, `second` and `millisecond`. +Use `Object.entries()` with `Array.prototype.filter()` to keep only non-zero values. +Use `Array.prototype.map()` to create the string for each value, pluralizing appropriately. +Use `String.prototype.join(', ')` to combine the values into a string. + ```js const formatDuration = ms => { if (ms < 0) ms = -ms; @@ -4295,39 +4296,39 @@ const formatDuration = ms => { ```js formatDuration(1001); // '1 second, 1 millisecond' formatDuration(34325055574); // '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds' -``` +```
    [⬆ Back to top](#contents) -### getColonTimeFromDate - -Returns a string of the form `HH:MM:SS` from a `Date` object. - -Use `Date.prototype.toTimeString()` and `String.prototype.slice()` to get the `HH:MM:SS` part of a given `Date` object. - +### getColonTimeFromDate + +Returns a string of the form `HH:MM:SS` from a `Date` object. + +Use `Date.prototype.toTimeString()` and `String.prototype.slice()` to get the `HH:MM:SS` part of a given `Date` object. + ```js -const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); +const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); ```
    Examples ```js -getColonTimeFromDate(new Date()); // "08:38:00" -``` +getColonTimeFromDate(new Date()); // "08:38:00" +```

    [⬆ Back to top](#contents) -### getDaysDiffBetweenDates - -Returns the difference (in days) between two dates. - -Calculate the difference (in days) between two `Date` objects. - +### getDaysDiffBetweenDates + +Returns the difference (in days) between two dates. + +Calculate the difference (in days) between two `Date` objects. + ```js const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24); @@ -4338,181 +4339,181 @@ const getDaysDiffBetweenDates = (dateInitial, dateFinal) => ```js getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9 -``` +```
    [⬆ Back to top](#contents) -### getMeridiemSuffixOfInteger - -Converts an integer to a suffixed string, adding `am` or `pm` based on its value. - -Use the modulo operator (`%`) and conditional checks to transform an integer to a stringified 12-hour format with meridiem suffix. - +### getMeridiemSuffixOfInteger + +Converts an integer to a suffixed string, adding `am` or `pm` based on its value. + +Use the modulo operator (`%`) and conditional checks to transform an integer to a stringified 12-hour format with meridiem suffix. + ```js -const getMeridiemSuffixOfInteger = num => - num === 0 || num === 24 - ? 12 + 'am' - : num === 12 - ? 12 + 'pm' - : num < 12 - ? (num % 12) + 'am' - : (num % 12) + 'pm'; +const getMeridiemSuffixOfInteger = num => + num === 0 || num === 24 + ? 12 + 'am' + : num === 12 + ? 12 + 'pm' + : num < 12 + ? (num % 12) + 'am' + : (num % 12) + 'pm'; ```
    Examples ```js -getMeridiemSuffixOfInteger(0); // "12am" -getMeridiemSuffixOfInteger(11); // "11am" -getMeridiemSuffixOfInteger(13); // "1pm" -getMeridiemSuffixOfInteger(25); // "1pm" -``` +getMeridiemSuffixOfInteger(0); // "12am" +getMeridiemSuffixOfInteger(11); // "11am" +getMeridiemSuffixOfInteger(13); // "1pm" +getMeridiemSuffixOfInteger(25); // "1pm" +```

    [⬆ Back to top](#contents) -### isAfterDate - -Check if a date is after another date. - -Use the greater than operator (`>`) to check if the first date comes after the second one. - +### isAfterDate + +Check if a date is after another date. + +Use the greater than operator (`>`) to check if the first date comes after the second one. + ```js -const isAfterDate = (dateA, dateB) => dateA > dateB; +const isAfterDate = (dateA, dateB) => dateA > dateB; ```
    Examples ```js -isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true -``` +isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true +```

    [⬆ Back to top](#contents) -### isBeforeDate - -Check if a date is before another date. - -Use the less than operator (`<`) to check if the first date comes before the second one. - +### isBeforeDate + +Check if a date is before another date. + +Use the less than operator (`<`) to check if the first date comes before the second one. + ```js -const isBeforeDate = (dateA, dateB) => dateA < dateB; +const isBeforeDate = (dateA, dateB) => dateA < dateB; ```
    Examples ```js -isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true -``` +isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true +```

    [⬆ Back to top](#contents) -### isSameDate - -Check if a date is the same as another date. - -Use `Date.prototype.toISOString()` and strict equality checking (`===`) to check if the first date is the same as the second one. - +### isSameDate + +Check if a date is the same as another date. + +Use `Date.prototype.toISOString()` and strict equality checking (`===`) to check if the first date is the same as the second one. + ```js -const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); +const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); ```
    Examples ```js -isSameDate(new Date(2010, 10, 20), new Date(2010, 10, 20)); // true -``` +isSameDate(new Date(2010, 10, 20), new Date(2010, 10, 20)); // true +```

    [⬆ Back to top](#contents) -### maxDate - -Returns the maximum of the given dates. - -Use `Math.max.apply()` to find the maximum date value, `new Date()` to convert it to a `Date` object. - +### maxDate + +Returns the maximum of the given dates. + +Use `Math.max.apply()` to find the maximum date value, `new Date()` to convert it to a `Date` object. + ```js -const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); +const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); ```
    Examples ```js -const array = [ - new Date(2017, 4, 13), - new Date(2018, 2, 12), - new Date(2016, 0, 10), - new Date(2016, 0, 9) -]; -maxDate(array); // 2018-03-11T22:00:00.000Z -``` +const array = [ + new Date(2017, 4, 13), + new Date(2018, 2, 12), + new Date(2016, 0, 10), + new Date(2016, 0, 9) +]; +maxDate(array); // 2018-03-11T22:00:00.000Z +```

    [⬆ Back to top](#contents) -### minDate - -Returns the minimum of the given dates. - -Use `Math.min.apply()` to find the minimum date value, `new Date()` to convert it to a `Date` object. - +### minDate + +Returns the minimum of the given dates. + +Use `Math.min.apply()` to find the minimum date value, `new Date()` to convert it to a `Date` object. + ```js -const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); +const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); ```
    Examples ```js -const array = [ - new Date(2017, 4, 13), - new Date(2018, 2, 12), - new Date(2016, 0, 10), - new Date(2016, 0, 9) -]; -minDate(array); // 2016-01-08T22:00:00.000Z -``` +const array = [ + new Date(2017, 4, 13), + new Date(2018, 2, 12), + new Date(2016, 0, 10), + new Date(2016, 0, 9) +]; +minDate(array); // 2016-01-08T22:00:00.000Z +```

    [⬆ Back to top](#contents) -### tomorrow - -Results in a string representation of tomorrow's date. - -Use `new Date()` to get the current date, increment by one using `Date.getDate()` and set the value to the result using `Date.setDate()`. -Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format. - +### tomorrow + +Results in a string representation of tomorrow's date. + +Use `new Date()` to get the current date, increment by one using `Date.getDate()` and set the value to the result using `Date.setDate()`. +Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format. + ```js -const tomorrow = () => { - let t = new Date(); - t.setDate(t.getDate() + 1); - return t.toISOString().split('T')[0]; -}; +const tomorrow = () => { + let t = new Date(); + t.setDate(t.getDate() + 1); + return t.toISOString().split('T')[0]; +}; ```
    Examples ```js -tomorrow(); // 2018-10-18 (if current date is 2018-10-18) -``` +tomorrow(); // 2018-10-18 (if current date is 2018-10-18) +```
    @@ -4523,12 +4524,12 @@ tomorrow(); // 2018-10-18 (if current date is 2018-10-18) ## 🎛️ Function -### attempt - -Attempts to invoke a function with the provided arguments, returning either the result or the caught error object. - -Use a `try... catch` block to return either the result of the function or an appropriate error. - +### attempt + +Attempts to invoke a function with the provided arguments, returning either the result or the caught error object. + +Use a `try... catch` block to return either the result of the function or an appropriate error. + ```js const attempt = (fn, ...args) => { try { @@ -4547,19 +4548,19 @@ var elements = attempt(function(selector) { return document.querySelectorAll(selector); }, '>_>'); if (elements instanceof Error) elements = []; // elements = [] -``` +```
    [⬆ Back to top](#contents) -### bind - -Creates a function that invokes `fn` with a given context, optionally adding any additional supplied parameters to the beginning of the arguments. - -Return a `function` that uses `Function.prototype.apply()` to apply the given `context` to `fn`. -Use `Array.prototype.concat()` to prepend any additional supplied parameters to the arguments. - +### bind + +Creates a function that invokes `fn` with a given context, optionally adding any additional supplied parameters to the beginning of the arguments. + +Return a `function` that uses `Function.prototype.apply()` to apply the given `context` to `fn`. +Use `Array.prototype.concat()` to prepend any additional supplied parameters to the arguments. + ```js const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); ``` @@ -4574,19 +4575,19 @@ function greet(greeting, punctuation) { const freddy = { user: 'fred' }; const freddyBound = bind(greet, freddy); console.log(freddyBound('hi', '!')); // 'hi fred!' -``` +```
    [⬆ Back to top](#contents) -### bindKey - -Creates a function that invokes the method at a given key of an object, optionally adding any additional supplied parameters to the beginning of the arguments. - -Return a `function` that uses `Function.prototype.apply()` to bind `context[fn]` to `context`. -Use the spread operator (`...`) to prepend any additional supplied parameters to the arguments. - +### bindKey + +Creates a function that invokes the method at a given key of an object, optionally adding any additional supplied parameters to the beginning of the arguments. + +Return a `function` that uses `Function.prototype.apply()` to bind `context[fn]` to `context`. +Use the spread operator (`...`) to prepend any additional supplied parameters to the arguments. + ```js const bindKey = (context, fn, ...boundArgs) => (...args) => context[fn].apply(context, [...boundArgs, ...args]); @@ -4604,88 +4605,88 @@ const freddy = { }; const freddyBound = bindKey(freddy, 'greet'); console.log(freddyBound('hi', '!')); // 'hi fred!' -``` +```
    [⬆ Back to top](#contents) -### chainAsync - -Chains asynchronous functions. - -Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed. - +### chainAsync + +Chains 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 last = fns[fns.length - 1]; - const next = () => { - const fn = fns[curr++]; - fn === last ? fn() : fn(next); - }; - next(); -}; +const chainAsync = fns => { + let curr = 0; + const last = fns[fns.length - 1]; + const next = () => { + const fn = fns[curr++]; + fn === last ? fn() : fn(next); + }; + next(); +}; ```
    Examples ```js -chainAsync([ - next => { - console.log('0 seconds'); - setTimeout(next, 1000); - }, - next => { - console.log('1 second'); - setTimeout(next, 1000); - }, - () => { - console.log('2 second'); - } -]); -``` +chainAsync([ + next => { + console.log('0 seconds'); + setTimeout(next, 1000); + }, + next => { + console.log('1 second'); + setTimeout(next, 1000); + }, + () => { + console.log('2 second'); + } +]); +```

    [⬆ Back to top](#contents) -### compose - -Performs right-to-left function composition. - -Use `Array.prototype.reduce()` to perform right-to-left function composition. -The last (rightmost) function can accept one or more arguments; the remaining functions must be unary. - +### compose + +Performs right-to-left function composition. + +Use `Array.prototype.reduce()` to perform right-to-left function composition. +The last (rightmost) function can accept one or more arguments; the remaining functions must be unary. + ```js -const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); +const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); ```
    Examples ```js -const add5 = x => x + 5; -const multiply = (x, y) => x * y; -const multiplyAndAdd5 = compose( - add5, - multiply -); -multiplyAndAdd5(5, 2); // 15 -``` +const add5 = x => x + 5; +const multiply = (x, y) => x * y; +const multiplyAndAdd5 = compose( + add5, + multiply +); +multiplyAndAdd5(5, 2); // 15 +```

    [⬆ Back to top](#contents) -### composeRight - -Performs left-to-right function composition. - -Use `Array.prototype.reduce()` to perform left-to-right function composition. -The first (leftmost) function can accept one or more arguments; the remaining functions must be unary. - +### composeRight + +Performs left-to-right function composition. + +Use `Array.prototype.reduce()` to perform left-to-right function composition. +The first (leftmost) function can accept one or more arguments; the remaining functions must be unary. + ```js const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); ``` @@ -4698,19 +4699,19 @@ const add = (x, y) => x + y; const square = x => x * x; const addAndSquare = composeRight(add, square); addAndSquare(1, 2); // 9 -``` +```
    [⬆ Back to top](#contents) -### converge - -Accepts a converging function and a list of branching functions and returns a function that applies each branching function to the arguments and the results of the branching functions are passed as arguments to the converging function. - -Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments. -Use the spread operator (`...`) to call `coverger` with the results of all other functions. - +### converge + +Accepts a converging function and a list of branching functions and returns a function that applies each branching function to the arguments and the results of the branching functions are passed as arguments to the converging function. + +Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments. +Use the spread operator (`...`) to call `coverger` with the results of all other functions. + ```js const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); ``` @@ -4724,21 +4725,21 @@ const average = converge((a, b) => a / b, [ arr => arr.length ]); average([1, 2, 3, 4, 5, 6, 7]); // 4 -``` +```
    [⬆ Back to top](#contents) -### curry - -Curries a function. - -Use recursion. -If the number of provided arguments (`args`) is sufficient, call the passed function `fn`. -Otherwise, return a curried function `fn` 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`. - +### curry + +Curries a function. + +Use recursion. +If the number of provided arguments (`args`) is sufficient, call the passed function `fn`. +Otherwise, return a curried function `fn` 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 = (fn, arity = fn.length, ...args) => arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); @@ -4750,19 +4751,19 @@ const curry = (fn, arity = fn.length, ...args) => ```js curry(Math.pow)(2)(10); // 1024 curry(Math.min, 3)(10)(50)(2); // 2 -``` +```
    [⬆ Back to top](#contents) -### debounce - -Creates a debounced function that delays invoking the provided function until at least `ms` milliseconds have elapsed since the last time it was invoked. - -Each time the debounced function is invoked, clear the current pending timeout with `clearTimeout()` and use `setTimeout()` to create a new timeout that delays invoking the function until at least `ms` milliseconds has elapsed. Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary arguments. -Omit the second argument, `ms`, to set the timeout at a default of 0 ms. - +### debounce + +Creates a debounced function that delays invoking the provided function until at least `ms` milliseconds have elapsed since the last time it was invoked. + +Each time the debounced function is invoked, clear the current pending timeout with `clearTimeout()` and use `setTimeout()` to create a new timeout that delays invoking the function until at least `ms` milliseconds has elapsed. Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary arguments. +Omit the second argument, `ms`, to set the timeout at a default of 0 ms. + ```js const debounce = (fn, ms = 0) => { let timeoutId; @@ -4784,46 +4785,46 @@ window.addEventListener( console.log(window.innerHeight); }, 250) ); // Will log the window dimensions at most every 250ms -``` +```
    [⬆ Back to top](#contents) -### defer - -Defers invoking a function until the current call stack has cleared. - -Use `setTimeout()` with a timeout of 1ms to add a new event to the browser event queue and allow the rendering engine to complete its work. Use the spread (`...`) operator to supply the function with an arbitrary number of arguments. - +### defer + +Defers invoking a function until the current call stack has cleared. + +Use `setTimeout()` with a timeout of 1ms to add a new event to the browser event queue and allow the rendering engine to complete its work. Use the spread (`...`) operator to supply the function with an arbitrary number of arguments. + ```js -const defer = (fn, ...args) => setTimeout(fn, 1, ...args); +const defer = (fn, ...args) => setTimeout(fn, 1, ...args); ```
    Examples ```js -// Example A: -defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a' - -// Example B: -document.querySelector('#someElement').innerHTML = 'Hello'; -longRunningFunction(); // Browser will not update the HTML until this has finished -defer(longRunningFunction); // Browser will update the HTML then run the function -``` +// Example A: +defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a' + +// Example B: +document.querySelector('#someElement').innerHTML = 'Hello'; +longRunningFunction(); // Browser will not update the HTML until this has finished +defer(longRunningFunction); // Browser will update the HTML then run the function +```

    [⬆ Back to top](#contents) -### delay - -Invokes the provided function after `wait` milliseconds. - -Use `setTimeout()` to delay execution of `fn`. -Use the spread (`...`) operator to supply the function with an arbitrary number of arguments. - +### delay + +Invokes the provided function after `wait` milliseconds. + +Use `setTimeout()` to delay execution of `fn`. +Use the spread (`...`) operator to supply the function with an arbitrary number of arguments. + ```js const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); ``` @@ -4839,18 +4840,18 @@ delay( 1000, 'later' ); // Logs 'later' after one second. -``` +```
    [⬆ Back to top](#contents) -### functionName - -Logs the name of a function. - -Use `console.debug()` and the `name` property of the passed method to log the method's name to the `debug` channel of the console. - +### functionName + +Logs the name of a function. + +Use `console.debug()` and the `name` property of the passed method to log the method's name to the `debug` channel of the console. + ```js const functionName = fn => (console.debug(fn.name), fn); ``` @@ -4860,50 +4861,50 @@ const functionName = fn => (console.debug(fn.name), fn); ```js functionName(Math.max); // max (logged in debug channel of console) -``` +```
    [⬆ Back to top](#contents) -### hz - -Returns the number of times a function executed per second. -`hz` is the unit for `hertz`, the unit of frequency defined as one cycle per second. - -Use `performance.now()` to get the difference in milliseconds before and after the iteration loop to calculate the time elapsed executing the function `iterations` times. -Return the number of cycles per second by converting milliseconds to seconds and dividing it by the time elapsed. -Omit the second argument, `iterations`, to use the default of 100 iterations. - +### hz + +Returns the number of times a function executed per second. +`hz` is the unit for `hertz`, the unit of frequency defined as one cycle per second. + +Use `performance.now()` to get the difference in milliseconds before and after the iteration loop to calculate the time elapsed executing the function `iterations` times. +Return the number of cycles per second by converting milliseconds to seconds and dividing it by the time elapsed. +Omit the second argument, `iterations`, to use the default of 100 iterations. + ```js -const hz = (fn, iterations = 100) => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return (1000 * iterations) / (performance.now() - before); -}; +const hz = (fn, iterations = 100) => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return (1000 * iterations) / (performance.now() - before); +}; ```
    Examples ```js -// 10,000 element array -const numbers = Array(10000) - .fill() - .map((_, i) => i); - -// Test functions with the same goal: sum up the elements in the array -const sumReduce = () => numbers.reduce((acc, n) => acc + n, 0); -const sumForLoop = () => { - let sum = 0; - for (let i = 0; i < numbers.length; i++) sum += numbers[i]; - return sum; -}; - -// `sumForLoop` is nearly 10 times faster -Math.round(hz(sumReduce)); // 572 -Math.round(hz(sumForLoop)); // 4784 -``` +// 10,000 element array +const numbers = Array(10000) + .fill() + .map((_, i) => i); + +// Test functions with the same goal: sum up the elements in the array +const sumReduce = () => numbers.reduce((acc, n) => acc + n, 0); +const sumForLoop = () => { + let sum = 0; + for (let i = 0; i < numbers.length; i++) sum += numbers[i]; + return sum; +}; + +// `sumForLoop` is nearly 10 times faster +Math.round(hz(sumReduce)); // 572 +Math.round(hz(sumForLoop)); // 4784 +```
    @@ -4943,12 +4944,12 @@ console.log(anagramsCached.cache); // The cached anagrams map
    [⬆ Back to top](#contents) -### negate - -Negates a predicate function. - -Take a predicate function and apply the not operator (`!`) to it with its arguments. - +### negate + +Negates a predicate function. + +Take a predicate function and apply the not operator (`!`) to it with its arguments. + ```js const negate = func => (...args) => !func(...args); ``` @@ -4958,19 +4959,19 @@ const negate = func => (...args) => !func(...args); ```js [1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ] -``` +```
    [⬆ Back to top](#contents) -### once - -Ensures a function is called only once. - -Utilizing a closure, use a flag, `called`, and set it to `true` once the function is called for the first time, preventing it from being called again. In order to allow the function to have its `this` context changed (such as in an event listener), the `function` keyword must be used, and the supplied function must have the context applied. -Allow the function to be supplied with an arbitrary number of arguments using the rest/spread (`...`) operator. - +### once + +Ensures a function is called only once. + +Utilizing a closure, use a flag, `called`, and set it to `true` once the function is called for the first time, preventing it from being called again. In order to allow the function to have its `this` context changed (such as in an event listener), the `function` keyword must be used, and the supplied function must have the context applied. +Allow the function to be supplied with an arbitrary number of arguments using the rest/spread (`...`) operator. + ```js const once = fn => { let called = false; @@ -4990,18 +4991,18 @@ const startApp = function(event) { console.log(this, event); // document.body, MouseEvent }; document.body.addEventListener('click', once(startApp)); // only runs `startApp` once upon click -``` +```
    [⬆ Back to top](#contents) -### partial - -Creates a function that invokes `fn` with `partials` prepended to the arguments it receives. - -Use the spread operator (`...`) to prepend `partials` to the list of arguments of `fn`. - +### partial + +Creates a function that invokes `fn` with `partials` prepended to the arguments it receives. + +Use the spread operator (`...`) to prepend `partials` to the list of arguments of `fn`. + ```js const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); ``` @@ -5013,18 +5014,18 @@ const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); const greet = (greeting, name) => greeting + ' ' + name + '!'; const greetHello = partial(greet, 'Hello'); greetHello('John'); // 'Hello John!' -``` +```
    [⬆ Back to top](#contents) -### partialRight - -Creates a function that invokes `fn` with `partials` appended to the arguments it receives. - -Use the spread operator (`...`) to append `partials` to the list of arguments of `fn`. - +### partialRight + +Creates a function that invokes `fn` with `partials` appended to the arguments it receives. + +Use the spread operator (`...`) to append `partials` to the list of arguments of `fn`. + ```js const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); ``` @@ -5036,18 +5037,18 @@ const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); const greet = (greeting, name) => greeting + ' ' + name + '!'; const greetJohn = partialRight(greet, 'John'); greetJohn('Hello'); // 'Hello John!' -``` +```
    [⬆ Back to top](#contents) -### runPromisesInSeries - -Runs an array of promises in series. - -Use `Array.prototype.reduce()` to create a promise chain, where each promise returns the next promise when resolved. - +### runPromisesInSeries + +Runs an array of promises in series. + +Use `Array.prototype.reduce()` to create a promise chain, where each promise returns the next promise when resolved. + ```js const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); ``` @@ -5058,18 +5059,18 @@ const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.r ```js const delay = d => new Promise(r => setTimeout(r, d)); runPromisesInSeries([() => delay(1000), () => delay(2000)]); // Executes each promise sequentially, taking a total of 3 seconds to complete -``` +```
    [⬆ Back to top](#contents) -### sleep - -Delays the execution of an asynchronous function. - -Delay executing part of an `async` function, by putting it to sleep, returning a `Promise`. - +### sleep + +Delays the execution of an asynchronous function. + +Delay executing part of an `async` function, by putting it to sleep, returning a `Promise`. + ```js const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); ``` @@ -5083,7 +5084,7 @@ async function sleepyWork() { await sleep(1000); console.log('I woke up after 1 second.'); } -``` +``` @@ -5138,13 +5139,13 @@ window.addEventListener(
    [⬆ Back to top](#contents) -### times - -Iterates over a callback `n` times - -Use `Function.call()` to call `fn` `n` times or until it returns `false`. -Omit the last argument, `context`, to use an `undefined` object (or the global object in non-strict mode). - +### times + +Iterates over a callback `n` times + +Use `Function.call()` to call `fn` `n` times or until it returns `false`. +Omit the last argument, `context`, to use an `undefined` object (or the global object in non-strict mode). + ```js const times = (n, fn, context = undefined) => { let i = 0; @@ -5159,22 +5160,22 @@ const times = (n, fn, context = undefined) => { var output = ''; times(5, i => (output += i)); console.log(output); // 01234 -``` +```
    [⬆ Back to top](#contents) -### uncurry - -Uncurries a function up to depth `n`. - -Return a variadic function. -Use `Array.prototype.reduce()` on the provided arguments to call each subsequent curry level of the function. -If the `length` of the provided arguments is less than `n` throw an error. -Otherwise, call `fn` with the proper amount of arguments, using `Array.prototype.slice(0, n)`. -Omit the second argument, `n`, to uncurry up to depth `1`. - +### uncurry + +Uncurries a function up to depth `n`. + +Return a variadic function. +Use `Array.prototype.reduce()` on the provided arguments to call each subsequent curry level of the function. +If the `length` of the provided arguments is less than `n` throw an error. +Otherwise, call `fn` with the proper amount of arguments, using `Array.prototype.slice(0, n)`. +Omit the second argument, `n`, to uncurry up to depth `1`. + ```js const uncurry = (fn, n = 1) => (...args) => { const next = acc => args => args.reduce((x, y) => x(y), acc); @@ -5190,19 +5191,19 @@ const uncurry = (fn, n = 1) => (...args) => { const add = x => y => z => x + y + z; const uncurriedAdd = uncurry(add, 3); uncurriedAdd(1, 2, 3); // 6 -``` +```
    [⬆ Back to top](#contents) -### unfold - -Builds an array, using an iterator function and an initial seed value. - -Use a `while` loop and `Array.prototype.push()` to call the function repeatedly until it returns `false`. -The iterator function accepts one argument (`seed`) and must always return an array with two elements ([`value`, `nextSeed`]) or `false` to terminate. - +### unfold + +Builds an array, using an iterator function and an initial seed value. + +Use a `while` loop and `Array.prototype.push()` to call the function repeatedly until it returns `false`. +The iterator function accepts one argument (`seed`) and must always return an array with two elements ([`value`, `nextSeed`]) or `false` to terminate. + ```js const unfold = (fn, seed) => { let result = [], @@ -5218,18 +5219,18 @@ const unfold = (fn, seed) => { ```js var f = n => (n > 50 ? false : [-n, n + 10]); unfold(f, 10); // [-10, -20, -30, -40, -50] -``` +```
    [⬆ Back to top](#contents) -### when - -Tests a value, `x`, against a predicate function. If `true`, return `fn(x)`. Else, return `x`. - -Return a function expecting a single value, `x`, that returns the appropriate value based on `pred`. - +### when + +Tests a value, `x`, against a predicate function. If `true`, return `fn(x)`. Else, return `x`. + +Return a function expecting a single value, `x`, that returns the appropriate value based on `pred`. + ```js const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); ``` @@ -5241,7 +5242,7 @@ const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); const doubleEvenNumbers = when(x => x % 2 === 0, x => x * 2); doubleEvenNumbers(2); // 4 doubleEvenNumbers(1); // 1 -``` +``` @@ -5252,13 +5253,13 @@ doubleEvenNumbers(1); // 1 ## ➗ Math -### approximatelyEqual - -Checks if two numbers are approximately equal to each other. - -Use `Math.abs()` to compare the absolute difference of the two values to `epsilon`. -Omit the third parameter, `epsilon`, to use a default value of `0.001`. - +### approximatelyEqual + +Checks if two numbers are approximately equal to each other. + +Use `Math.abs()` to compare the absolute difference of the two values to `epsilon`. +Omit the third parameter, `epsilon`, to use a default value of `0.001`. + ```js const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; ``` @@ -5268,18 +5269,18 @@ const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsi ```js approximatelyEqual(Math.PI / 2.0, 1.5708); // true -``` +```
    [⬆ Back to top](#contents) -### average - -Returns the average of two or more numbers. - -Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. - +### average + +Returns the average of two or more numbers. + +Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. + ```js const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; ``` @@ -5290,18 +5291,18 @@ const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.leng ```js average(...[1, 2, 3]); // 2 average(1, 2, 3); // 2 -``` +```
    [⬆ Back to top](#contents) -### averageBy - -Returns the average of an array, after mapping each element to a value using the provided function. - -Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. - +### averageBy + +Returns the average of an array, after mapping each element to a value using the provided function. + +Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. + ```js const averageBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / @@ -5314,22 +5315,22 @@ const averageBy = (arr, fn) => ```js averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5 averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5 -``` +```
    [⬆ Back to top](#contents) -### binomialCoefficient - -Evaluates the binomial coefficient of two integers `n` and `k`. - -Use `Number.isNaN()` to check if any of the two values is `NaN`. -Check if `k` is less than `0`, greater than or equal to `n`, equal to `1` or `n - 1` and return the appropriate result. -Check if `n - k` is less than `k` and switch their values accordingly. -Loop from `2` through `k` and calculate the binomial coefficient. -Use `Math.round()` to account for rounding errors in the calculation. - +### binomialCoefficient + +Evaluates the binomial coefficient of two integers `n` and `k`. + +Use `Number.isNaN()` to check if any of the two values is `NaN`. +Check if `k` is less than `0`, greater than or equal to `n`, equal to `1` or `n - 1` and return the appropriate result. +Check if `n - k` is less than `k` and switch their values accordingly. +Loop from `2` through `k` and calculate the binomial coefficient. +Use `Math.round()` to account for rounding errors in the calculation. + ```js const binomialCoefficient = (n, k) => { if (Number.isNaN(n) || Number.isNaN(k)) return NaN; @@ -5348,19 +5349,19 @@ const binomialCoefficient = (n, k) => { ```js binomialCoefficient(8, 2); // 28 -``` +```
    [⬆ Back to top](#contents) -### clampNumber - -Clamps `num` within the inclusive range specified by the boundary values `a` and `b`. - -If `num` falls within the range, return `num`. -Otherwise, return the nearest number in the range. - +### clampNumber + +Clamps `num` within the inclusive range specified by the boundary values `a` and `b`. + +If `num` falls within the range, return `num`. +Otherwise, return the nearest number in the range. + ```js const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); ``` @@ -5371,40 +5372,40 @@ const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math. ```js clampNumber(2, 3, 5); // 3 clampNumber(1, -1, -5); // -1 -``` +```
    [⬆ Back to top](#contents) -### degreesToRads - -Converts an angle from degrees to radians. - -Use `Math.PI` and the degree to radian formula to convert the angle from degrees to radians. - +### degreesToRads + +Converts an angle from degrees to radians. + +Use `Math.PI` and the degree to radian formula to convert the angle from degrees to radians. + ```js -const degreesToRads = deg => (deg * Math.PI) / 180.0; +const degreesToRads = deg => (deg * Math.PI) / 180.0; ```
    Examples ```js -degreesToRads(90.0); // ~1.5708 -``` +degreesToRads(90.0); // ~1.5708 +```

    [⬆ Back to top](#contents) -### digitize - -Converts a number to an array of digits. - -Convert the number to a string, using the spread operator (`...`) to build an array. -Use `Array.prototype.map()` and `parseInt()` to transform each value to an integer. - +### digitize + +Converts a number to an array of digits. + +Convert the number to a string, using the spread operator (`...`) to build an array. +Use `Array.prototype.map()` and `parseInt()` to transform each value to an integer. + ```js const digitize = n => [...`${n}`].map(i => parseInt(i)); ``` @@ -5414,18 +5415,18 @@ const digitize = n => [...`${n}`].map(i => parseInt(i)); ```js digitize(123); // [1, 2, 3] -``` +```
    [⬆ Back to top](#contents) -### distance - -Returns the distance between two points. - -Use `Math.hypot()` to calculate the Euclidean distance between two points. - +### distance + +Returns the 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); ``` @@ -5435,7 +5436,7 @@ const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); ```js distance(1, 1, 2, 3); // 2.23606797749979 -``` +``` @@ -5491,45 +5492,45 @@ own individual rating by supplying it as the third argument.
    [⬆ Back to top](#contents) -### factorial - -Calculates the factorial of a number. - -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`. -Throws an exception if `n` is a negative number. - -```js - -const factorial = n => - n < 0 - ? (() => { - throw new TypeError('Negative numbers are not allowed!'); - })() - : n <= 1 - ? 1 - : n * factorial(n - 1); +### factorial + +Calculates the factorial of a number. + +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`. +Throws an exception if `n` is a negative number. + +```js + +const factorial = n => + n < 0 + ? (() => { + throw new TypeError('Negative numbers are not allowed!'); + })() + : n <= 1 + ? 1 + : n * factorial(n - 1); ```
    Examples -```js -factorial(6); // 720 -``` +```js +factorial(6); // 720 +```

    [⬆ Back to top](#contents) -### fibonacci - -Generates an array, containing the Fibonacci sequence, up until the nth term. - -Create an empty array of the specific length, initializing the first two values (`0` and `1`). -Use `Array.prototype.reduce()` to add values into the array, using the sum of the last two values, except for the first two. - +### fibonacci + +Generates an array, containing the Fibonacci sequence, up until the nth term. + +Create an empty array of the specific length, initializing the first two values (`0` and `1`). +Use `Array.prototype.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.from({ length: n }).reduce( @@ -5543,20 +5544,20 @@ const fibonacci = n => ```js fibonacci(6); // [0, 1, 1, 2, 3, 5] -``` +```
    [⬆ Back to top](#contents) -### gcd - -Calculates the greatest common divisor between two or more numbers/arrays. - -The inner `_gcd` function uses 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`. - +### gcd + +Calculates the greatest common divisor between two or more numbers/arrays. + +The inner `_gcd` function uses 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 = (...arr) => { const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); @@ -5570,21 +5571,21 @@ const gcd = (...arr) => { ```js gcd(8, 36); // 4 gcd(...[12, 8, 32]); // 4 -``` +```
    [⬆ Back to top](#contents) -### geometricProgression - -Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive and the ratio between two terms is `step`. -Returns an error if `step` equals `1`. - -Use `Array.from()`, `Math.log()` and `Math.floor()` to create an array of the desired length, `Array.prototype.map()` to fill with the desired values in a range. -Omit the second argument, `start`, to use a default value of `1`. -Omit the third argument, `step`, to use a default value of `2`. - +### geometricProgression + +Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive and the ratio between two terms is `step`. +Returns an error if `step` equals `1`. + +Use `Array.from()`, `Math.log()` and `Math.floor()` to create an array of the desired length, `Array.prototype.map()` to fill with the desired values in a range. +Omit the second argument, `start`, to use a default value of `1`. +Omit the third argument, `step`, to use a default value of `2`. + ```js const geometricProgression = (end, start = 1, step = 2) => Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( @@ -5599,19 +5600,19 @@ const geometricProgression = (end, start = 1, step = 2) => geometricProgression(256); // [1, 2, 4, 8, 16, 32, 64, 128, 256] geometricProgression(256, 3); // [3, 6, 12, 24, 48, 96, 192] geometricProgression(256, 1, 4); // [1, 4, 16, 64, 256] -``` +```
    [⬆ Back to top](#contents) -### hammingDistance - -Calculates the Hamming distance between two values. - -Use XOR operator (`^`) to find the bit difference between the two numbers, convert to a binary string using `toString(2)`. -Count and return the number of `1`s in the string, using `match(/1/g)`. - +### hammingDistance + +Calculates the Hamming distance between two values. + +Use XOR operator (`^`) to find the bit difference between the two numbers, convert to a 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; ``` @@ -5621,19 +5622,19 @@ const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) | ```js hammingDistance(2, 3); // 1 -``` +```
    [⬆ Back to top](#contents) -### inRange - -Checks if the given number falls within the given range. - -Use arithmetic comparison to check if the given number is in the specified range. -If the second parameter, `end`, is not specified, the range is considered to be from `0` to `start`. - +### inRange + +Checks if the given number falls within the given range. + +Use arithmetic comparison to check if the given number is in the specified range. +If the second parameter, `end`, is not specified, the range is considered to be from `0` to `start`. + ```js const inRange = (n, start, end = null) => { if (end && start > end) [end, start] = [start, end]; @@ -5649,18 +5650,18 @@ inRange(3, 2, 5); // true inRange(3, 4); // true inRange(2, 3, 5); // false inRange(3, 2); // false -``` +```
    [⬆ Back to top](#contents) -### isDivisible - -Checks if the first numeric argument is divisible by the second one. - -Use the modulo operator (`%`) to check if the remainder is equal to `0`. - +### isDivisible + +Checks if the first numeric argument is divisible by the second one. + +Use the modulo operator (`%`) to check if the remainder is equal to `0`. + ```js const isDivisible = (dividend, divisor) => dividend % divisor === 0; ``` @@ -5670,19 +5671,19 @@ const isDivisible = (dividend, divisor) => dividend % divisor === 0; ```js isDivisible(6, 3); // true -``` +```
    [⬆ Back to top](#contents) -### isEven - -Returns `true` if the given number is even, `false` otherwise. - -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. - +### isEven + +Returns `true` if the given number is even, `false` otherwise. + +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; ``` @@ -5692,41 +5693,41 @@ const isEven = num => num % 2 === 0; ```js isEven(3); // false -``` +```
    [⬆ Back to top](#contents) -### isNegativeZero - -Checks if the given value is equal to negative zero (`-0`). - -Checks whether a passed value is equal to `0` and if `1` divided by the value equals `-Infinity`. - +### isNegativeZero + +Checks if the given value is equal to negative zero (`-0`). + +Checks whether a passed value is equal to `0` and if `1` divided by the value equals `-Infinity`. + ```js -const isNegativeZero = val => val === 0 && 1 / val === -Infinity; +const isNegativeZero = val => val === 0 && 1 / val === -Infinity; ```
    Examples ```js -isNegativeZero(-0); // true -isNegativeZero(0); // false -``` +isNegativeZero(-0); // true +isNegativeZero(0); // false +```

    [⬆ Back to top](#contents) -### isPrime - -Checks if the provided integer is a prime number. - -Check numbers from `2` to the square root of the given number. -Return `false` if any of them divides the given number, else return `true`, unless the number is less than `2`. - +### isPrime + +Checks if the provided integer is a prime number. + +Check numbers from `2` to the square root of the given number. +Return `false` if any of them divides the given number, else return `true`, unless the number is less than `2`. + ```js const isPrime = num => { const boundary = Math.floor(Math.sqrt(num)); @@ -5740,34 +5741,34 @@ const isPrime = num => { ```js isPrime(11); // true -``` +```
    [⬆ Back to top](#contents) -### lcm - -Returns the least common multiple of two or more numbers. - -Use the greatest common divisor (GCD) formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. -The GCD formula uses recursion. - +### lcm + +Returns the least common multiple of two or more numbers. + +Use the greatest common divisor (GCD) formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. +The GCD formula uses recursion. + ```js -const lcm = (...arr) => { - const gcd = (x, y) => (!y ? x : gcd(y, x % y)); - const _lcm = (x, y) => (x * y) / gcd(x, y); - return [...arr].reduce((a, b) => _lcm(a, b)); -}; +const lcm = (...arr) => { + const gcd = (x, y) => (!y ? x : gcd(y, x % y)); + const _lcm = (x, y) => (x * y) / gcd(x, y); + return [...arr].reduce((a, b) => _lcm(a, b)); +}; ```
    Examples ```js -lcm(12, 7); // 84 -lcm(...[1, 3, 4, 5]); // 60 -``` +lcm(12, 7); // 84 +lcm(...[1, 3, 4, 5]); // 60 +```
    @@ -5809,12 +5810,33 @@ luhnCheck(123456789); // false
    [⬆ Back to top](#contents) -### maxBy +### mapNumRange + +Maps a number from one range to another range. + +Returns `num` mapped between `outMin`-`outMax` from `inMin`-`inMax`. + +```js +const mapNumRange = (num, inMin, inMax, outMin, outMax) => (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; +``` -Returns the maximum value of an array, after mapping each element to a value using the provided function. +
    +Examples -Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Math.max()` to get the maximum value. +```js +mapNumRange(5,0,10,0,100); // 50 +``` +
    + +
    [⬆ Back to top](#contents) + +### maxBy + +Returns the maximum value of an array, after mapping each element to a value using the provided function. + +Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Math.max()` to get the maximum value. + ```js const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); ``` @@ -5825,19 +5847,19 @@ const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : v ```js maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 8 maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 8 -``` +```
    [⬆ Back to top](#contents) -### median - -Returns the median of an array of numbers. - -Find the middle of the array, use `Array.prototype.sort()` to sort the values. -Return the number at the midpoint if `length` is odd, otherwise the average of the two middle numbers. - +### median + +Returns the median of an array of numbers. + +Find the middle of the array, use `Array.prototype.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), @@ -5851,42 +5873,42 @@ const median = arr => { ```js median([5, 6, 50, 1, -5]); // 5 -``` +```
    [⬆ Back to top](#contents) -### midpoint - -Calculates the midpoint between two pairs of (x,y) points. - -Destructure the array to get `x1`, `y1`, `x2` and `y2`, calculate the midpoint for each dimension by dividing the sum of the two endpoints by `2`. - +### midpoint + +Calculates the midpoint between two pairs of (x,y) points. + +Destructure the array to get `x1`, `y1`, `x2` and `y2`, calculate the midpoint for each dimension by dividing the sum of the two endpoints by `2`. + ```js -const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2]; +const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2]; ```
    Examples ```js -midpoint([2, 2], [4, 4]); // [3, 3] -midpoint([4, 4], [6, 6]); // [5, 5] -midpoint([1, 3], [2, 4]); // [1.5, 3.5] -``` - +midpoint([2, 2], [4, 4]); // [3, 3] +midpoint([4, 4], [6, 6]); // [5, 5] +midpoint([1, 3], [2, 4]); // [1.5, 3.5] +``` +

    [⬆ Back to top](#contents) -### minBy - -Returns the minimum value of an array, after mapping each element to a value using the provided function. - -Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Math.min()` to get the maximum value. - +### minBy + +Returns the minimum value of an array, after mapping each element to a value using the provided function. + +Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Math.min()` to get the maximum value. + ```js const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); ``` @@ -5897,40 +5919,40 @@ const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : v ```js minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 2 minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 2 -``` +```
    [⬆ Back to top](#contents) -### percentile - -Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value. - -Use `Array.prototype.reduce()` to calculate how many numbers are below the value and how many are the same value and apply the percentile formula. - +### percentile + +Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value. + +Use `Array.prototype.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; +const percentile = (arr, val) => + (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; ```
    Examples ```js -percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6); // 55 -``` +percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6); // 55 +```

    [⬆ Back to top](#contents) -### powerset - -Returns the powerset of a given array of numbers. - -Use `Array.prototype.reduce()` combined with `Array.prototype.map()` to iterate over elements and combine into an array containing all combinations. - +### powerset + +Returns the powerset of a given array of numbers. + +Use `Array.prototype.reduce()` combined with `Array.prototype.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))), [[]]); ``` @@ -5940,18 +5962,18 @@ const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))) ```js powerset([1, 2]); // [[], [1], [2], [2, 1]] -``` +```
    [⬆ Back to top](#contents) -### primes - -Generates primes up to a given number, using the Sieve of Eratosthenes. - -Generate an array from `2` to the given number. Use `Array.prototype.filter()` to filter out the values divisible by any number from `2` to the square root of the provided number. - +### primes + +Generates primes up to a given number, using the Sieve of Eratosthenes. + +Generate an array from `2` to the given number. Use `Array.prototype.filter()` to filter out the values divisible by any number from `2` to the square root of the provided number. + ```js const primes = num => { let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), @@ -5967,39 +5989,39 @@ const primes = num => { ```js primes(10); // [2,3,5,7] -``` +```
    [⬆ Back to top](#contents) -### radsToDegrees - -Converts an angle from radians to degrees. - -Use `Math.PI` and the radian to degree formula to convert the angle from radians to degrees. - +### radsToDegrees + +Converts an angle from radians to degrees. + +Use `Math.PI` and the radian to degree formula to convert the angle from radians to degrees. + ```js -const radsToDegrees = rad => (rad * 180.0) / Math.PI; +const radsToDegrees = rad => (rad * 180.0) / Math.PI; ```
    Examples ```js -radsToDegrees(Math.PI / 2); // 90 -``` +radsToDegrees(Math.PI / 2); // 90 +```

    [⬆ Back to top](#contents) -### randomIntArrayInRange - -Returns an array of n random integers in the specified range. - -Use `Array.from()` to create an empty array of the specific length, `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. - +### randomIntArrayInRange + +Returns an array of n random integers in the specified range. + +Use `Array.from()` to create an empty array of the specific length, `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. + ```js const randomIntArrayInRange = (min, max, n = 1) => Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); @@ -6010,18 +6032,18 @@ const randomIntArrayInRange = (min, max, n = 1) => ```js randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ] -``` +```
    [⬆ Back to top](#contents) -### randomIntegerInRange - -Returns a random integer in the specified range. - -Use `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. - +### randomIntegerInRange + +Returns a random integer in the specified 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; ``` @@ -6031,18 +6053,18 @@ const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min ```js randomIntegerInRange(0, 5); // 2 -``` +```
    [⬆ Back to top](#contents) -### randomNumberInRange - -Returns a random number in the specified range. - -Use `Math.random()` to generate a random value, map it to the desired range using multiplication. - +### randomNumberInRange + +Returns a random number in the specified range. + +Use `Math.random()` to generate a random value, map it to the desired range using multiplication. + ```js const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; ``` @@ -6052,19 +6074,19 @@ const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; ```js randomNumberInRange(2, 10); // 6.0211363285087005 -``` +```
    [⬆ Back to top](#contents) -### round - -Rounds a number to a specified amount of digits. - -Use `Math.round()` and template literals to round the number to the specified number of digits. -Omit the second argument, `decimals` to round to an integer. - +### round + +Rounds a number to a specified amount of digits. + +Use `Math.round()` and template literals to round the number to the specified number of digits. +Omit the second argument, `decimals` to round to an integer. + ```js const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); ``` @@ -6074,18 +6096,18 @@ const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${ ```js round(1.005, 2); // 1.01 -``` +```
    [⬆ Back to top](#contents) -### sdbm - -Hashes the input string into a whole number. - -Use `String.prototype.split('')` and `Array.prototype.reduce()` to create a hash of the input string, utilizing bit shifting. - +### sdbm + +Hashes the input string into a whole number. + +Use `String.prototype.split('')` and `Array.prototype.reduce()` to create a hash of the input string, utilizing bit shifting. + ```js const sdbm = str => { let arr = str.split(''); @@ -6102,20 +6124,20 @@ const sdbm = str => { ```js sdbm('name'); // -3521204949 -``` +```
    [⬆ Back to top](#contents) -### standardDeviation - -Returns the standard deviation of an array of numbers. - -Use `Array.prototype.reduce()` to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then -determine the standard deviation. -You can omit the second argument to get the sample standard deviation or set it to `true` to get the population standard deviation. - +### standardDeviation + +Returns the standard deviation of an array of numbers. + +Use `Array.prototype.reduce()` to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then +determine the standard deviation. +You can omit the second argument to get the sample standard deviation or set it to `true` to get the population standard deviation. + ```js const standardDeviation = (arr, usePopulation = false) => { const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; @@ -6132,40 +6154,40 @@ const standardDeviation = (arr, usePopulation = false) => { ```js standardDeviation([10, 2, 38, 23, 38, 23, 21]); // 13.284434142114991 (sample) standardDeviation([10, 2, 38, 23, 38, 23, 21], true); // 12.29899614287479 (population) -``` +```
    [⬆ Back to top](#contents) -### sum - -Returns the sum of two or more numbers/arrays. - -Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`. - +### sum + +Returns the sum of two or more numbers/arrays. + +Use `Array.prototype.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); +const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); ```
    Examples ```js -sum(1, 2, 3, 4); // 10 -sum(...[1, 2, 3, 4]); // 10 -``` +sum(1, 2, 3, 4); // 10 +sum(...[1, 2, 3, 4]); // 10 +```

    [⬆ Back to top](#contents) -### sumBy - -Returns the sum of an array, after mapping each element to a value using the provided function. - -Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`. - +### sumBy + +Returns the sum of an array, after mapping each element to a value using the provided function. + +Use `Array.prototype.map()` to map each element to the value returned by `fn`, `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`. + ```js const sumBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); @@ -6177,48 +6199,48 @@ const sumBy = (arr, fn) => ```js sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 20 sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 20 -``` +```
    [⬆ Back to top](#contents) -### sumPower - -Returns the sum of the powers of all the numbers from `start` to `end` (both inclusive). - -Use `Array.prototype.fill()` to create an array of all the numbers in the target range, `Array.prototype.map()` and the exponent operator (`**`) to raise them to `power` and `Array.prototype.reduce()` to add them together. -Omit the second argument, `power`, to use a default power of `2`. -Omit the third argument, `start`, to use a default starting value of `1`. - +### sumPower + +Returns the sum of the powers of all the numbers from `start` to `end` (both inclusive). + +Use `Array.prototype.fill()` to create an array of all the numbers in the target range, `Array.prototype.map()` and the exponent operator (`**`) to raise them to `power` and `Array.prototype.reduce()` to add them together. +Omit the second argument, `power`, to use a default power of `2`. +Omit the third argument, `start`, to use a default starting value of `1`. + ```js -const sumPower = (end, power = 2, start = 1) => - Array(end + 1 - start) - .fill(0) - .map((x, i) => (i + start) ** power) - .reduce((a, b) => a + b, 0); +const sumPower = (end, power = 2, start = 1) => + Array(end + 1 - start) + .fill(0) + .map((x, i) => (i + start) ** power) + .reduce((a, b) => a + b, 0); ```
    Examples ```js -sumPower(10); // 385 -sumPower(10, 3); // 3025 -sumPower(10, 3, 5); // 2925 -``` +sumPower(10); // 385 +sumPower(10, 3); // 3025 +sumPower(10, 3, 5); // 2925 +```

    [⬆ Back to top](#contents) -### toSafeInteger - -Converts a value to a safe integer. - -Use `Math.max()` and `Math.min()` to find the closest safe value. -Use `Math.round()` to convert to an integer. - +### toSafeInteger + +Converts a value to a safe integer. + +Use `Math.max()` and `Math.min()` to find the closest safe value. +Use `Math.round()` to convert to an integer. + ```js const toSafeInteger = num => Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); @@ -6230,7 +6252,7 @@ const toSafeInteger = num => ```js toSafeInteger('3.2'); // 3 toSafeInteger(Infinity); // 9007199254740991 -``` +``` @@ -6241,55 +6263,55 @@ toSafeInteger(Infinity); // 9007199254740991 ## 📦 Node -### atob - -Decodes a string of data which has been encoded using base-64 encoding. - -Create a `Buffer` for the given string with base-64 encoding and use `Buffer.toString('binary')` to return the decoded string. - +### atob + +Decodes a string of data which has been encoded using base-64 encoding. + +Create a `Buffer` for the given string with base-64 encoding and use `Buffer.toString('binary')` to return the decoded string. + ```js -const atob = str => Buffer.from(str, 'base64').toString('binary'); +const atob = str => Buffer.from(str, 'base64').toString('binary'); ```
    Examples ```js -atob('Zm9vYmFy'); // 'foobar' -``` +atob('Zm9vYmFy'); // 'foobar' +```

    [⬆ Back to top](#contents) -### btoa - -Creates a base-64 encoded ASCII string from a String object in which each character in the string is treated as a byte of binary data. - -Create a `Buffer` for the given string with binary encoding and use `Buffer.toString('base64')` to return the encoded string. - +### btoa + +Creates a base-64 encoded ASCII string from a String object in which each character in the string is treated as a byte of binary data. + +Create a `Buffer` for the given string with binary encoding and use `Buffer.toString('base64')` to return the encoded string. + ```js -const btoa = str => Buffer.from(str, 'binary').toString('base64'); +const btoa = str => Buffer.from(str, 'binary').toString('base64'); ```
    Examples ```js -btoa('foobar'); // 'Zm9vYmFy' -``` +btoa('foobar'); // 'Zm9vYmFy' +```

    [⬆ Back to top](#contents) -### colorize - -Add special characters to text to print in color in the console (combined with `console.log()`). - -Use template literals and special characters to add the appropriate color code to the string output. -For background colors, add a special character that resets the background color at the end of the string. - +### colorize + +Add special characters to text to print in color in the console (combined with `console.log()`). + +Use template literals and special characters to add the appropriate color code to the string output. +For background colors, add a special character that resets the background color at the end of the string. + ```js const colorize = (...args) => ({ black: `\x1b[30m${args.join(' ')}`, @@ -6318,41 +6340,41 @@ const colorize = (...args) => ({ console.log(colorize('foo').red); // 'foo' (red letters) console.log(colorize('foo', 'bar').bgBlue); // 'foo bar' (blue background) console.log(colorize(colorize('foo').yellow, colorize('foo').green).bgWhite); // 'foo bar' (first word in yellow letters, second word in green letters, white background for both) -``` +```
    [⬆ Back to top](#contents) -### createDirIfNotExists - -Creates a directory, if it does not exist. - -Use `fs.existsSync()` to check if the directory exists, `fs.mkdirSync()` to create it. - +### createDirIfNotExists + +Creates a directory, if it does not exist. + +Use `fs.existsSync()` to check if the directory exists, `fs.mkdirSync()` to create it. + ```js -const fs = require('fs'); -const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); +const fs = require('fs'); +const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); ```
    Examples ```js -createDirIfNotExists('test'); // creates the directory 'test', if it doesn't exist -``` +createDirIfNotExists('test'); // creates the directory 'test', if it doesn't exist +```

    [⬆ Back to top](#contents) -### hasFlags - -Check if the current process's arguments contain the specified flags. - -Use `Array.prototype.every()` and `Array.prototype.includes()` to check if `process.argv` contains all the specified flags. -Use a regular expression to test if the specified flags are prefixed with `-` or `--` and prefix them accordingly. - +### hasFlags + +Check if the current process's arguments contain the specified flags. + +Use `Array.prototype.every()` and `Array.prototype.includes()` to check if `process.argv` contains all the specified flags. +Use a regular expression to test if the specified flags are prefixed with `-` or `--` and prefix them accordingly. + ```js const hasFlags = (...flags) => flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); @@ -6366,132 +6388,132 @@ const hasFlags = (...flags) => hasFlags('-s'); // true hasFlags('--test', 'cool=true', '-s'); // true hasFlags('special'); // false -``` +```
    [⬆ Back to top](#contents) -### hashNode +### hashNode + +Creates a hash for a value using the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) algorithm. Returns a promise. + +Use `crypto` API to create a hash for the given value, `setTimeout` to prevent blocking on a long operation, and a `Promise` to give it a familiar interface. + +```js +const crypto = require('crypto'); +const hashNode = val => + new Promise(resolve => + setTimeout( + () => + resolve( + crypto + .createHash('sha256') + .update(val) + .digest('hex') + ), + 0 + ) + ); +``` -Creates a hash for a value using the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) algorithm. Returns a promise. +
    +Examples -Use `crypto` API to create a hash for the given value, `setTimeout` to prevent blocking on a long operation, and a `Promise` to give it a familiar interface. +```js +hashNode(JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })).then(console.log); // '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393' +``` +
    + +
    [⬆ Back to top](#contents) + +### isDuplexStream + +Checks if the given argument is a duplex (readable and writable) stream. + +Check if the value is different from `null`, use `typeof` to check if a value is of type `object` and the `pipe` property is of type `function`. +Additionally check if the `typeof` the `_read`, `_write` and `_readableState`, `_writableState` properties are `function` and `object` respectively. + ```js -const crypto = require('crypto'); -const hashNode = val => - new Promise(resolve => - setTimeout( - () => - resolve( - crypto - .createHash('sha256') - .update(val) - .digest('hex') - ), - 0 - ) - ); +const isDuplexStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; ```
    Examples ```js -hashNode(JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })).then(console.log); // '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393' -``` +const Stream = require('stream'); +isDuplexStream(new Stream.Duplex()); // true +```

    [⬆ Back to top](#contents) -### isDuplexStream - -Checks if the given argument is a duplex (readable and writable) stream. - -Check if the value is different from `null`, use `typeof` to check if a value is of type `object` and the `pipe` property is of type `function`. -Additionally check if the `typeof` the `_read`, `_write` and `_readableState`, `_writableState` properties are `function` and `object` respectively. - +### isReadableStream + +Checks if the given argument is a readable stream. + +Check if the value is different from `null`, use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`. +Additionally check if the `typeof` the `_read` and `_readableState` properties are `function` and `object` respectively. + ```js -const isDuplexStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; +const isReadableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object'; ```
    Examples ```js -const Stream = require('stream'); -isDuplexStream(new Stream.Duplex()); // true -``` +const fs = require('fs'); +isReadableStream(fs.createReadStream('test.txt')); // true +```

    [⬆ Back to top](#contents) -### isReadableStream - -Checks if the given argument is a readable stream. - -Check if the value is different from `null`, use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`. -Additionally check if the `typeof` the `_read` and `_readableState` properties are `function` and `object` respectively. - +### isStream + +Checks if the given argument is a stream. + +Check if the value is different from `null`, use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`. + ```js -const isReadableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object'; +const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; ```
    Examples ```js -const fs = require('fs'); -isReadableStream(fs.createReadStream('test.txt')); // true -``` +const fs = require('fs'); +isStream(fs.createReadStream('test.txt')); // true +```

    [⬆ Back to top](#contents) -### isStream - -Checks if the given argument is a stream. - -Check if the value is different from `null`, use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`. - -```js -const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; -``` - -
    -Examples - -```js -const fs = require('fs'); -isStream(fs.createReadStream('test.txt')); // true -``` - -
    - -
    [⬆ Back to top](#contents) - -### isTravisCI - -Checks if the current environment is [Travis CI](https://travis-ci.org/). - -Checks if the current environment has the `TRAVIS` and `CI` environment variables ([reference](https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables)). - +### isTravisCI + +Checks if the current environment is [Travis CI](https://travis-ci.org/). + +Checks if the current environment has the `TRAVIS` and `CI` environment variables ([reference](https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables)). + ```js const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; ``` @@ -6501,46 +6523,46 @@ const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; ```js isTravisCI(); // true (if code is running on Travis CI) -``` +```
    [⬆ Back to top](#contents) -### isWritableStream - -Checks if the given argument is a writable stream. - -Check if the value is different from `null`, use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`. -Additionally check if the `typeof` the `_write` and `_writableState` properties are `function` and `object` respectively. - +### isWritableStream + +Checks if the given argument is a writable stream. + +Check if the value is different from `null`, use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`. +Additionally check if the `typeof` the `_write` and `_writableState` properties are `function` and `object` respectively. + ```js -const isWritableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; +const isWritableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; ```
    Examples ```js -const fs = require('fs'); -isWritableStream(fs.createWriteStream('test.txt')); // true -``` +const fs = require('fs'); +isWritableStream(fs.createWriteStream('test.txt')); // true +```

    [⬆ Back to top](#contents) -### JSONToFile - -Writes a JSON object to a file. - -Use `fs.writeFile()`, template literals and `JSON.stringify()` to write a `json` object to a `.json` file. - +### JSONToFile + +Writes a JSON object to a file. + +Use `fs.writeFile()`, template literals and `JSON.stringify()` to write a `json` object to a `.json` file. + ```js const fs = require('fs'); const JSONToFile = (obj, filename) => @@ -6552,20 +6574,20 @@ const JSONToFile = (obj, filename) => ```js JSONToFile({ test: 'is passed' }, 'testJsonFile'); // writes the object to 'testJsonFile.json' -``` +```
    [⬆ Back to top](#contents) -### readFileLines - -Returns an array of lines from the specified file. - -Use `readFileSync` function in `fs` node package to create a `Buffer` from a file. -convert buffer to string using `toString(encoding)` function. -creating an array from contents of file by `split`ing file content line by line (each `\n`). - +### readFileLines + +Returns an array of lines from the specified file. + +Use `readFileSync` function in `fs` node package to create a `Buffer` from a file. +convert buffer to string using `toString(encoding)` function. +creating an array from contents of file by `split`ing file content line by line (each `\n`). + ```js const fs = require('fs'); const readFileLines = filename => @@ -6579,28 +6601,28 @@ const readFileLines = filename => Examples ```js -/* -contents of test.txt : - line1 - line2 - line3 - ___________________________ +/* +contents of test.txt : + line1 + line2 + line3 + ___________________________ */ let arr = readFileLines('test.txt'); console.log(arr); // ['line1', 'line2', 'line3'] -``` - +``` +
    [⬆ Back to top](#contents) -### untildify - -Converts a tilde path to an absolute path. - -Use `String.prototype.replace()` with a regular expression and `OS.homedir()` to replace the `~` in the start of the path with the home directory. - +### untildify + +Converts a tilde path to an absolute path. + +Use `String.prototype.replace()` with a regular expression and `OS.homedir()` to replace the `~` in the start of the path with the home directory. + ```js const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); ``` @@ -6610,18 +6632,18 @@ const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$ ```js untildify('~/node'); // '/Users/aUser/node' -``` +```
    [⬆ Back to top](#contents) -### UUIDGeneratorNode - -Generates a UUID in Node.JS. - -Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4. - +### UUIDGeneratorNode + +Generates a UUID in Node.JS. + +Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4. + ```js const crypto = require('crypto'); const UUIDGeneratorNode = () => @@ -6635,7 +6657,7 @@ const UUIDGeneratorNode = () => ```js UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc' -``` +``` @@ -6646,12 +6668,12 @@ UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc' ## 🗃️ Object -### bindAll - -Binds methods of an object to the object itself, overwriting the existing method. - -Use `Array.prototype.forEach()` to return a `function` that uses `Function.prototype.apply()` to apply the given context (`obj`) to `fn` for each function specified. - +### bindAll + +Binds methods of an object to the object itself, overwriting the existing method. + +Use `Array.prototype.forEach()` to return a `function` that uses `Function.prototype.apply()` to apply the given context (`obj`) to `fn` for each function specified. + ```js const bindAll = (obj, ...fns) => fns.forEach( @@ -6676,71 +6698,71 @@ var view = { }; bindAll(view, 'click'); jQuery(element).on('click', view.click); // Logs 'clicked docs' when clicked. -``` +```
    [⬆ Back to top](#contents) -### deepClone - -Creates a deep clone of an object. - -Use recursion. -Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original. -Use `Object.keys()` and `Array.prototype.forEach()` to determine which key-value pairs need to be deep cloned. - +### deepClone + +Creates a deep clone of an object. + +Use recursion. +Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original. +Use `Object.keys()` and `Array.prototype.forEach()` to determine which key-value pairs need to be deep cloned. + ```js -const deepClone = obj => { - let clone = Object.assign({}, obj); - Object.keys(clone).forEach( - key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) - ); - return Array.isArray(obj) && obj.length - ? (clone.length = obj.length) && Array.from(clone) - : Array.isArray(obj) - ? Array.from(obj) - : clone; -}; +const deepClone = obj => { + let clone = Object.assign({}, obj); + Object.keys(clone).forEach( + key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) + ); + return Array.isArray(obj) && obj.length + ? (clone.length = obj.length) && Array.from(clone) + : Array.isArray(obj) + ? Array.from(obj) + : clone; +}; ```
    Examples ```js -const a = { foo: 'bar', obj: { a: 1, b: 2 } }; -const b = deepClone(a); // a !== b, a.obj !== b.obj -``` +const a = { foo: 'bar', obj: { a: 1, b: 2 } }; +const b = deepClone(a); // a !== b, a.obj !== b.obj +```

    [⬆ Back to top](#contents) -### deepFreeze - -Deep freezes an object. - -Calls `Object.freeze(obj)` recursively on all unfrozen properties of passed object that are `instanceof` object. - +### deepFreeze + +Deep freezes an object. + +Calls `Object.freeze(obj)` recursively on all unfrozen properties of passed object that are `instanceof` object. + ```js -const deepFreeze = obj => - Object.keys(obj).forEach( - prop => - !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) - ) || Object.freeze(obj); +const deepFreeze = obj => + Object.keys(obj).forEach( + prop => + !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) + ) || Object.freeze(obj); ```
    Examples ```js -'use strict'; - -const o = deepFreeze([1, [2, 3]]); - -o[0] = 3; // not allowed -o[1][0] = 4; // not allowed as well -``` +'use strict'; + +const o = deepFreeze([1, [2, 3]]); + +o[0] = 3; // not allowed +o[1][0] = 4; // not allowed as well +```
    @@ -6807,12 +6829,12 @@ const upperKeysObj = deepMapKeys(obj, key => key.toUpperCase());
    [⬆ Back to top](#contents) -### defaults - -Assigns default values for all properties in an object that are `undefined`. - -Use `Object.assign()` to create a new empty object and copy the original one to maintain key order, use `Array.prototype.reverse()` and the spread operator `...` to combine the default values from left to right, finally use `obj` again to overwrite properties that originally had a value. - +### defaults + +Assigns default values for all properties in an object that are `undefined`. + +Use `Object.assign()` to create a new empty object and copy the original one to maintain key order, use `Array.prototype.reverse()` and the spread operator `...` to combine the default values from left to right, finally use `obj` again to overwrite properties that originally had a value. + ```js const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); ``` @@ -6822,44 +6844,44 @@ const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj ```js defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 } -``` +```
    [⬆ Back to top](#contents) -### dig - -Returns the target value in a nested JSON object, based on the given key. - -Use the `in` operator to check if `target` exists in `obj`. -If found, return the value of `obj[target]`, otherwise use `Object.values(obj)` and `Array.prototype.reduce()` to recursively call `dig` on each nested object until the first matching key/value pair is found. - -```js - -const dig = (obj, target) => - target in obj - ? obj[target] - : Object.values(obj).reduce((acc, val) => { - if (acc !== undefined) return acc; - if (typeof val === 'object') return dig(val, target); - }, undefined); +### dig + +Returns the target value in a nested JSON object, based on the given key. + +Use the `in` operator to check if `target` exists in `obj`. +If found, return the value of `obj[target]`, otherwise use `Object.values(obj)` and `Array.prototype.reduce()` to recursively call `dig` on each nested object until the first matching key/value pair is found. + +```js + +const dig = (obj, target) => + target in obj + ? obj[target] + : Object.values(obj).reduce((acc, val) => { + if (acc !== undefined) return acc; + if (typeof val === 'object') return dig(val, target); + }, undefined); ```
    Examples -```js -const data = { - level1: { - level2: { - level3: 'some data' - } - } -}; -dig(data, 'level3'); // 'some data' -dig(data, 'level4'); // undefined -``` +```js +const data = { + level1: { + level2: { + level3: 'some data' + } + } +}; +dig(data, 'level3'); // 'some data' +dig(data, 'level4'); // undefined +```
    @@ -6897,12 +6919,12 @@ equals({ a: [2, { e: 3 }], b: [4], c: 'foo' }, { a: [2, { e: 3 }], b: [4], c: 'f
    [⬆ Back to top](#contents) -### findKey - -Returns the first key that satisfies the provided testing function. Otherwise `undefined` is returned. - -Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.find()` to test the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object. - +### findKey + +Returns the first key that satisfies the provided testing function. Otherwise `undefined` is returned. + +Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.find()` to test the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object. + ```js const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); ``` @@ -6919,20 +6941,20 @@ findKey( }, o => o['active'] ); // 'barney' -``` +```
    [⬆ Back to top](#contents) -### findLastKey - -Returns the last key that satisfies the provided testing function. -Otherwise `undefined` is returned. - -Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.reverse()` to reverse their order and `Array.prototype.find()` to test the provided function for each key-value pair. -The callback receives three arguments - the value, the key and the object. - +### findLastKey + +Returns the last key that satisfies the provided testing function. +Otherwise `undefined` is returned. + +Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.reverse()` to reverse their order and `Array.prototype.find()` to test the provided function for each key-value pair. +The callback receives three arguments - the value, the key and the object. + ```js const findLastKey = (obj, fn) => Object.keys(obj) @@ -6952,22 +6974,22 @@ findLastKey( }, o => o['active'] ); // 'pebbles' -``` +```
    [⬆ Back to top](#contents) -### flattenObject - -Flatten an object with the paths for keys. - -Use recursion. -Use `Object.keys(obj)` combined with `Array.prototype.reduce()` to convert every leaf node to a flattened path node. -If the value of a key is an object, the function calls itself with the appropriate `prefix` to create the path using `Object.assign()`. -Otherwise, it adds the appropriate prefixed key-value pair to the accumulator object. -You should always omit the second argument, `prefix`, unless you want every key to have a prefix. - +### flattenObject + +Flatten an object with the paths for keys. + +Use recursion. +Use `Object.keys(obj)` combined with `Array.prototype.reduce()` to convert every leaf node to a flattened path node. +If the value of a key is an object, the function calls itself with the appropriate `prefix` to create the path using `Object.assign()`. +Otherwise, it adds the appropriate prefixed key-value pair to the accumulator object. +You should always omit the second argument, `prefix`, unless you want every key to have a prefix. + ```js const flattenObject = (obj, prefix = '') => Object.keys(obj).reduce((acc, k) => { @@ -6983,18 +7005,18 @@ const flattenObject = (obj, prefix = '') => ```js flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 } -``` +```
    [⬆ Back to top](#contents) -### forOwn - -Iterates over all own properties of an object, running a callback for each one. - -Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.forEach()` to run the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object. - +### forOwn + +Iterates over all own properties of an object, running a callback for each one. + +Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.forEach()` to run the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object. + ```js const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); ``` @@ -7004,18 +7026,18 @@ const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, ob ```js forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1 -``` +```
    [⬆ Back to top](#contents) -### forOwnRight - -Iterates over all own properties of an object in reverse, running a callback for each one. - -Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.reverse()` to reverse their order and `Array.prototype.forEach()` to run the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object. - +### forOwnRight + +Iterates over all own properties of an object in reverse, running a callback for each one. + +Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.reverse()` to reverse their order and `Array.prototype.forEach()` to run the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object. + ```js const forOwnRight = (obj, fn) => Object.keys(obj) @@ -7028,21 +7050,21 @@ const forOwnRight = (obj, fn) => ```js forOwnRight({ foo: 'bar', a: 1 }, v => console.log(v)); // 1, 'bar' -``` +```
    [⬆ Back to top](#contents) -### functions - -Returns an array of function property names from own (and optionally inherited) enumerable properties of an object. - -Use `Object.keys(obj)` to iterate over the object's own properties. -If `inherited` is `true`, use `Object.get.PrototypeOf(obj)` to also get the object's inherited properties. -Use `Array.prototype.filter()` to keep only those properties that are functions. -Omit the second argument, `inherited`, to not include inherited properties by default. - +### functions + +Returns an array of function property names from own (and optionally inherited) enumerable properties of an object. + +Use `Object.keys(obj)` to iterate over the object's own properties. +If `inherited` is `true`, use `Object.get.PrototypeOf(obj)` to also get the object's inherited properties. +Use `Array.prototype.filter()` to keep only those properties that are functions. +Omit the second argument, `inherited`, to not include inherited properties by default. + ```js const functions = (obj, inherited = false) => (inherited @@ -7062,18 +7084,18 @@ function Foo() { Foo.prototype.c = () => 3; functions(new Foo()); // ['a', 'b'] functions(new Foo(), true); // ['a', 'b', 'c'] -``` +```
    [⬆ Back to top](#contents) -### get - -Retrieve a set of properties indicated by the given selectors from an object. - -Use `Array.prototype.map()` for each selector, `String.prototype.replace()` to replace square brackets with dots, `String.prototype.split('.')` to split each selector, `Array.prototype.filter()` to remove empty values and `Array.prototype.reduce()` to get the value indicated by it. - +### get + +Retrieve a set of properties indicated by the given selectors from an object. + +Use `Array.prototype.map()` for each selector, `String.prototype.replace()` to replace square brackets with dots, `String.prototype.split('.')` to split each selector, `Array.prototype.filter()` to remove empty values and `Array.prototype.reduce()` to get the value indicated by it. + ```js const get = (from, ...selectors) => [...selectors].map(s => @@ -7091,19 +7113,19 @@ const get = (from, ...selectors) => ```js const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] }; get(obj, 'selector.to.val', 'target[0]', 'target[2].a'); // ['val to select', 1, 'test'] -``` +```
    [⬆ Back to top](#contents) -### invertKeyValues - -Inverts the key-value pairs of an object, without mutating it. The corresponding inverted value of each inverted key is an array of keys responsible for generating the inverted value. If a function is supplied, it is applied to each inverted key. - -Use `Object.keys()` and `Array.prototype.reduce()` to invert the key-value pairs of an object and apply the function provided (if any). -Omit the second argument, `fn`, to get the inverted keys without applying a function to them. - +### invertKeyValues + +Inverts the key-value pairs of an object, without mutating it. The corresponding inverted value of each inverted key is an array of keys responsible for generating the inverted value. If a function is supplied, it is applied to each inverted key. + +Use `Object.keys()` and `Array.prototype.reduce()` to invert the key-value pairs of an object and apply the function provided (if any). +Omit the second argument, `fn`, to get the inverted keys without applying a function to them. + ```js const invertKeyValues = (obj, fn) => Object.keys(obj).reduce((acc, key) => { @@ -7120,19 +7142,19 @@ const invertKeyValues = (obj, fn) => ```js invertKeyValues({ a: 1, b: 2, c: 1 }); // { 1: [ 'a', 'c' ], 2: [ 'b' ] } invertKeyValues({ a: 1, b: 2, c: 1 }, value => 'group' + value); // { group1: [ 'a', 'c' ], group2: [ 'b' ] } -``` +```
    [⬆ Back to top](#contents) -### lowercaseKeys - -Creates a new object from the specified object, where all the keys are in lowercase. - -Use `Object.keys()` and `Array.prototype.reduce()` to create a new object from the specified object. -Convert each key in the original object to lowercase, using `String.toLowerCase()`. - +### lowercaseKeys + +Creates a new object from the specified object, where all the keys are in lowercase. + +Use `Object.keys()` and `Array.prototype.reduce()` to create a new object from the specified object. +Convert each key in the original object to lowercase, using `String.toLowerCase()`. + ```js const lowercaseKeys = obj => Object.keys(obj).reduce((acc, key) => { @@ -7147,19 +7169,19 @@ const lowercaseKeys = obj => ```js const myObj = { Name: 'Adam', sUrnAME: 'Smith' }; const myObjLower = lowercaseKeys(myObj); // {name: 'Adam', surname: 'Smith'}; -``` +```
    [⬆ Back to top](#contents) -### mapKeys - -Creates an object with keys generated by running the provided function for each key and the same values as the provided object. - -Use `Object.keys(obj)` to iterate over the object's keys. -Use `Array.prototype.reduce()` to create a new object with the same values and mapped keys using `fn`. - +### mapKeys + +Creates an object with keys generated by running the provided function for each key and the same values as the provided object. + +Use `Object.keys(obj)` to iterate over the object's keys. +Use `Array.prototype.reduce()` to create a new object with the same values and mapped keys using `fn`. + ```js const mapKeys = (obj, fn) => Object.keys(obj).reduce((acc, k) => { @@ -7173,19 +7195,19 @@ const mapKeys = (obj, fn) => ```js mapKeys({ a: 1, b: 2 }, (val, key) => key + val); // { a1: 1, b2: 2 } -``` +```
    [⬆ Back to top](#contents) -### mapValues - -Creates an object with the same keys as the provided object and values generated by running the provided function for each value. - -Use `Object.keys(obj)` to iterate over the object's keys. -Use `Array.prototype.reduce()` to create a new object with the same keys and mapped values using `fn`. - +### mapValues + +Creates an object with the same keys as the provided object and values generated by running the provided function for each value. + +Use `Object.keys(obj)` to iterate over the object's keys. +Use `Array.prototype.reduce()` to create a new object with the same keys and mapped values using `fn`. + ```js const mapValues = (obj, fn) => Object.keys(obj).reduce((acc, k) => { @@ -7203,18 +7225,18 @@ const users = { pebbles: { user: 'pebbles', age: 1 } }; mapValues(users, u => u.age); // { fred: 40, pebbles: 1 } -``` +```
    [⬆ Back to top](#contents) -### matches - -Compares two objects to determine if the first one contains equivalent property values to the second one. - -Use `Object.keys(source)` to get all the keys of the second object, then `Array.prototype.every()`, `Object.hasOwnProperty()` and strict comparison to determine if all keys exist in the first object and have the same values. - +### matches + +Compares two objects to determine if the first one contains equivalent property values to the second one. + +Use `Object.keys(source)` to get all the keys of the second object, then `Array.prototype.every()`, `Object.hasOwnProperty()` and strict comparison to determine if all keys exist in the first object and have the same values. + ```js const matches = (obj, source) => Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); @@ -7226,19 +7248,19 @@ const matches = (obj, source) => ```js matches({ age: 25, hair: 'long', beard: true }, { hair: 'long', beard: true }); // true matches({ hair: 'long', beard: true }, { age: 25, hair: 'long', beard: true }); // false -``` +```
    [⬆ Back to top](#contents) -### matchesWith - -Compares two objects to determine if the first one contains equivalent property values to the second one, based on a provided function. - -Use `Object.keys(source)` to get all the keys of the second object, then `Array.prototype.every()`, `Object.hasOwnProperty()` and the provided function to determine if all keys exist in the first object and have equivalent values. -If no function is provided, the values will be compared using the equality operator. - +### matchesWith + +Compares two objects to determine if the first one contains equivalent property values to the second one, based on a provided function. + +Use `Object.keys(source)` to get all the keys of the second object, then `Array.prototype.every()`, `Object.hasOwnProperty()` and the provided function to determine if all keys exist in the first object and have equivalent values. +If no function is provided, the values will be compared using the equality operator. + ```js const matchesWith = (obj, source, fn) => Object.keys(source).every( @@ -7259,19 +7281,19 @@ matchesWith( { greeting: 'hi' }, (oV, sV) => isGreeting(oV) && isGreeting(sV) ); // true -``` +```
    [⬆ Back to top](#contents) -### merge - -Creates a new object from the combination of two or more objects. - -Use `Array.prototype.reduce()` combined with `Object.keys(obj)` to iterate over all objects and keys. -Use `hasOwnProperty()` and `Array.prototype.concat()` to append values for keys existing in multiple objects. - +### merge + +Creates a new object from the combination of two or more objects. + +Use `Array.prototype.reduce()` combined with `Object.keys(obj)` to iterate over all objects and keys. +Use `hasOwnProperty()` and `Array.prototype.concat()` to append values for keys existing in multiple objects. + ```js const merge = (...objs) => [...objs].reduce( @@ -7298,22 +7320,22 @@ const other = { c: 'foo' }; merge(object, other); // { a: [ { x: 2 }, { y: 4 }, { z: 3 } ], b: [ 1, 2, 3 ], c: 'foo' } -``` +```
    [⬆ Back to top](#contents) -### nest - -Given a flat array of objects linked to one another, it will nest them recursively. -Useful for nesting comments, such as the ones on reddit.com. - -Use recursion. -Use `Array.prototype.filter()` to filter the items where the `id` matches the `link`, then `Array.prototype.map()` to map each one to a new object that has a `children` property which recursively nests the items based on which ones are children of the current item. -Omit the second argument, `id`, to default to `null` which indicates the object is not linked to another one (i.e. it is a top level object). -Omit the third argument, `link`, to use `'parent_id'` as the default property which links the object to another one by its `id`. - +### nest + +Given a flat array of objects linked to one another, it will nest them recursively. +Useful for nesting comments, such as the ones on reddit.com. + +Use recursion. +Use `Array.prototype.filter()` to filter the items where the `id` matches the `link`, then `Array.prototype.map()` to map each one to a new object that has a `children` property which recursively nests the items based on which ones are children of the current item. +Omit the second argument, `id`, to default to `null` which indicates the object is not linked to another one (i.e. it is a top level object). +Omit the third argument, `link`, to use `'parent_id'` as the default property which links the object to another one by its `id`. + ```js const nest = (items, id = null, link = 'parent_id') => items @@ -7334,19 +7356,19 @@ const comments = [ { id: 5, parent_id: 4 } ]; const nestedComments = nest(comments); // [{ id: 1, parent_id: null, children: [...] }] -``` - +``` +
    [⬆ Back to top](#contents) -### objectFromPairs - -Creates an object from the given key-value pairs. - -Use `Array.prototype.reduce()` to create and combine key-value pairs. - +### objectFromPairs + +Creates an object from the given key-value pairs. + +Use `Array.prototype.reduce()` to create and combine key-value pairs. + ```js const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); ``` @@ -7356,18 +7378,18 @@ const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a) ```js objectFromPairs([['a', 1], ['b', 2]]); // {a: 1, b: 2} -``` +```
    [⬆ Back to top](#contents) -### objectToPairs - -Creates an array of key-value pair arrays from an object. - -Use `Object.keys()` and `Array.prototype.map()` to iterate over the object's keys and produce an array with key-value pairs. - +### objectToPairs + +Creates an array of key-value pair arrays from an object. + +Use `Object.keys()` and `Array.prototype.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]]); ``` @@ -7377,19 +7399,19 @@ const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); ```js objectToPairs({ a: 1, b: 2 }); // [ ['a', 1], ['b', 2] ] -``` +```
    [⬆ Back to top](#contents) -### omit - -Omits the key-value pairs corresponding to the given keys from an object. - -Use `Object.keys(obj)`, `Array.prototype.filter()` and `Array.prototype.includes()` to remove the provided keys. -Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs. - +### omit + +Omits the key-value pairs corresponding to the given keys from an object. + +Use `Object.keys(obj)`, `Array.prototype.filter()` and `Array.prototype.includes()` to remove the provided keys. +Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs. + ```js const omit = (obj, arr) => Object.keys(obj) @@ -7402,19 +7424,19 @@ const omit = (obj, arr) => ```js omit({ a: 1, b: '2', c: 3 }, ['b']); // { 'a': 1, 'c': 3 } -``` +```
    [⬆ Back to top](#contents) -### omitBy - -Creates an object composed of the properties the given function returns falsey for. The function is invoked with two arguments: (value, key). - -Use `Object.keys(obj)` and `Array.prototype.filter()`to remove the keys for which `fn` returns a truthy value. -Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs. - +### omitBy + +Creates an object composed of the properties the given function returns falsey for. The function is invoked with two arguments: (value, key). + +Use `Object.keys(obj)` and `Array.prototype.filter()`to remove the keys for which `fn` returns a truthy value. +Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs. + ```js const omitBy = (obj, fn) => Object.keys(obj) @@ -7427,19 +7449,19 @@ const omitBy = (obj, fn) => ```js omitBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { b: '2' } -``` +```
    [⬆ Back to top](#contents) -### orderBy - -Returns a sorted array of objects ordered by properties and orders. - -Uses `Array.prototype.sort()`, `Array.prototype.reduce()` on the `props` array with a default value of `0`, use array destructuring to swap the properties position depending on the order passed. -If no `orders` array is passed it sort by `'asc'` by default. - +### orderBy + +Returns a sorted array of objects ordered by properties and orders. + +Uses `Array.prototype.sort()`, `Array.prototype.reduce()` on the `props` array with a default value of `0`, use array destructuring to swap the properties position depending on the order passed. +If no `orders` array is passed it sort by `'asc'` by default. + ```js const orderBy = (arr, props, orders) => [...arr].sort((a, b) => @@ -7460,18 +7482,18 @@ const orderBy = (arr, props, orders) => const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fred', age: 40 }]; orderBy(users, ['name', 'age'], ['asc', 'desc']); // [{name: 'barney', age: 36}, {name: 'fred', age: 48}, {name: 'fred', age: 40}] orderBy(users, ['name', 'age']); // [{name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}] -``` +```
    [⬆ Back to top](#contents) -### pick - -Picks the key-value pairs corresponding to the given keys from an object. - -Use `Array.prototype.reduce()` to convert the filtered/picked keys back to an object with the corresponding key-value pairs if the key exists in the object. - +### pick + +Picks the key-value pairs corresponding to the given keys from an object. + +Use `Array.prototype.reduce()` to convert the filtered/picked keys back to an object with the corresponding key-value pairs if the key exists in the object. + ```js const pick = (obj, arr) => arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); @@ -7482,19 +7504,19 @@ const pick = (obj, arr) => ```js pick({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 } -``` +```
    [⬆ Back to top](#contents) -### pickBy - -Creates an object composed of the properties the given function returns truthy for. The function is invoked with two arguments: (value, key). - -Use `Object.keys(obj)` and `Array.prototype.filter()`to remove the keys for which `fn` returns a falsey value. -Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs. - +### pickBy + +Creates an object composed of the properties the given function returns truthy for. The function is invoked with two arguments: (value, key). + +Use `Object.keys(obj)` and `Array.prototype.filter()`to remove the keys for which `fn` returns a falsey value. +Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs. + ```js const pickBy = (obj, fn) => Object.keys(obj) @@ -7507,18 +7529,18 @@ const pickBy = (obj, fn) => ```js pickBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { 'a': 1, 'c': 3 } -``` +```
    [⬆ Back to top](#contents) -### renameKeys - -Replaces the names of multiple object keys with the values provided. - -Use `Object.keys()` in combination with `Array.prototype.reduce()` and the spread operator (`...`) to get the object's keys and rename them according to `keysMap`. - +### renameKeys + +Replaces the names of multiple object keys with the values provided. + +Use `Object.keys()` in combination with `Array.prototype.reduce()` and the spread operator (`...`) to get the object's keys and rename them according to `keysMap`. + ```js const renameKeys = (keysMap, obj) => Object.keys(obj).reduce( @@ -7536,18 +7558,18 @@ const renameKeys = (keysMap, obj) => ```js const obj = { name: 'Bobo', job: 'Front-End Master', shoeSize: 100 }; renameKeys({ name: 'firstName', job: 'passion' }, obj); // { firstName: 'Bobo', passion: 'Front-End Master', shoeSize: 100 } -``` +```
    [⬆ Back to top](#contents) -### shallowClone - -Creates a shallow clone of an object. - -Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original. - +### shallowClone + +Creates a shallow clone of an object. + +Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original. + ```js const shallowClone = obj => Object.assign({}, obj); ``` @@ -7558,23 +7580,23 @@ const shallowClone = obj => Object.assign({}, obj); ```js const a = { x: true, y: 1 }; const b = shallowClone(a); // a !== b -``` +```
    [⬆ Back to top](#contents) -### size - -Get size of arrays, objects or strings. - -Get type of `val` (`array`, `object` or `string`). -Use `length` property for arrays. -Use `length` or `size` value if available or number of keys for objects. -Use `size` of a [`Blob` object](https://developer.mozilla.org/en-US/docs/Web/API/Blob) created from `val` for strings. - -Split strings into array of characters with `split('')` and return its length. - +### size + +Get size of arrays, objects or strings. + +Get type of `val` (`array`, `object` or `string`). +Use `length` property for arrays. +Use `length` or `size` value if available or number of keys for objects. +Use `size` of a [`Blob` object](https://developer.mozilla.org/en-US/docs/Web/API/Blob) created from `val` for strings. + +Split strings into array of characters with `split('')` and return its length. + ```js const size = val => Array.isArray(val) @@ -7593,18 +7615,18 @@ const size = val => size([1, 2, 3, 4, 5]); // 5 size('size'); // 4 size({ one: 1, two: 2, three: 3 }); // 3 -``` +```
    [⬆ Back to top](#contents) -### transform - -Applies a function against an accumulator and each key in the object (from left to right). - -Use `Object.keys(obj)` to iterate over each key in the object, `Array.prototype.reduce()` to call the apply the specified function against the given accumulator. - +### transform + +Applies a function against an accumulator and each key in the object (from left to right). + +Use `Object.keys(obj)` to iterate over each key in the object, `Array.prototype.reduce()` to call the apply the specified function against the given accumulator. + ```js const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); ``` @@ -7621,18 +7643,18 @@ transform( }, {} ); // { '1': ['a', 'c'], '2': ['b'] } -``` +```
    [⬆ Back to top](#contents) -### truthCheckCollection - -Checks if the predicate (second argument) is truthy on all elements of a collection (first argument). - -Use `Array.prototype.every()` to check if each passed object has the specified property and if it returns a truthy value. - +### truthCheckCollection + +Checks if the predicate (second argument) is truthy on all elements of a collection (first argument). + +Use `Array.prototype.every()` to check if each passed object has the specified property and if it returns a truthy value. + ```js const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); ``` @@ -7642,7 +7664,7 @@ const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pr ```js truthCheckCollection([{ user: 'Tinky-Winky', sex: 'male' }, { user: 'Dipsy', sex: 'male' }], 'sex'); // true -``` +``` @@ -7691,12 +7713,12 @@ unflattenObject({ 'a.b.c': 1, d: 1 }); // { a: { b: { c: 1 } }, d: 1 } ## 📜 String -### byteSize - -Returns the length of a string in bytes. - -Convert a given string to a [`Blob` Object](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and find its `size`. - +### byteSize + +Returns the length of a string in bytes. + +Convert a given string to a [`Blob` Object](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and find its `size`. + ```js const byteSize = str => new Blob([str]).size; ``` @@ -7707,19 +7729,19 @@ const byteSize = str => new Blob([str]).size; ```js byteSize('😀'); // 4 byteSize('Hello World'); // 11 -``` +```
    [⬆ Back to top](#contents) -### capitalize - -Capitalizes the first letter of a string. - -Use array destructuring and `String.prototype.toUpperCase()` to capitalize first letter, `...rest` to get array of characters after first letter and then `Array.prototype.join('')` to make it a string again. -Omit the `lowerRest` parameter to keep the rest of the string intact, or set it to `true` to convert to lowercase. - +### capitalize + +Capitalizes the first letter of a string. + +Use array destructuring and `String.prototype.toUpperCase()` to capitalize first letter, `...rest` to get array of characters after first letter and then `Array.prototype.join('')` to make it a string again. +Omit the `lowerRest` parameter to keep the rest of the string intact, or set it to `true` to convert to lowercase. + ```js const capitalize = ([first, ...rest], lowerRest = false) => first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); @@ -7731,18 +7753,18 @@ const capitalize = ([first, ...rest], lowerRest = false) => ```js capitalize('fooBar'); // 'FooBar' capitalize('fooBar', true); // 'Foobar' -``` +```
    [⬆ Back to top](#contents) -### capitalizeEveryWord - -Capitalizes the first letter of every word in a string. - -Use `String.prototype.replace()` to match the first character of each word and `String.prototype.toUpperCase()` to capitalize it. - +### capitalizeEveryWord + +Capitalizes the first letter of every word in a string. + +Use `String.prototype.replace()` to match the first character of each word and `String.prototype.toUpperCase()` to capitalize it. + ```js const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); ``` @@ -7752,43 +7774,43 @@ const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperC ```js capitalizeEveryWord('hello world!'); // 'Hello World!' -``` +```
    [⬆ Back to top](#contents) -### compactWhitespace - -Returns a string with whitespaces compacted. - -Use `String.prototype.replace()` with a regular expression to replace all occurences of 2 or more whitespace characters with a single space. - +### compactWhitespace + +Returns a string with whitespaces compacted. + +Use `String.prototype.replace()` with a regular expression to replace all occurences of 2 or more whitespace characters with a single space. + ```js -const compactWhitespace = str => str.replace(/\s{2,}/g, ' '); +const compactWhitespace = str => str.replace(/\s{2,}/g, ' '); ```
    Examples ```js -compactWhitespace('Lorem Ipsum'); // 'Lorem Ipsum' -compactWhitespace('Lorem \n Ipsum'); // 'Lorem Ipsum' -``` +compactWhitespace('Lorem Ipsum'); // 'Lorem Ipsum' +compactWhitespace('Lorem \n Ipsum'); // 'Lorem Ipsum' +```

    [⬆ Back to top](#contents) -### CSVToArray - -Converts a comma-separated values (CSV) string to a 2D array. - -Use `Array.prototype.slice()` and `Array.prototype.indexOf('\n')` to remove the first row (title row) if `omitFirstRow` is `true`. -Use `String.prototype.split('\n')` to create a string for each row, then `String.prototype.split(delimiter)` to separate the values in each row. -Omit the second argument, `delimiter`, to use a default delimiter of `,`. -Omit the third argument, `omitFirstRow`, to include the first row (title row) of the CSV string. - +### CSVToArray + +Converts a comma-separated values (CSV) string to a 2D array. + +Use `Array.prototype.slice()` and `Array.prototype.indexOf('\n')` to remove the first row (title row) if `omitFirstRow` is `true`. +Use `String.prototype.split('\n')` to create a string for each row, then `String.prototype.split(delimiter)` to separate the values in each row. +Omit the second argument, `delimiter`, to use a default delimiter of `,`. +Omit the third argument, `omitFirstRow`, to include the first row (title row) of the CSV string. + ```js const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => data @@ -7804,7 +7826,7 @@ const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => CSVToArray('a,b\nc,d'); // [['a','b'],['c','d']]; CSVToArray('a;b\nc;d', ';'); // [['a','b'],['c','d']]; CSVToArray('col1,col2\na,b\nc,d', ',', true); // [['a','b'],['c','d']]; -``` +``` @@ -7845,13 +7867,13 @@ CSVToJSON('col1;col2\na;b\nc;d', ';'); // [{'col1': 'a', 'col2': 'b'}, {'col1':
    [⬆ Back to top](#contents) -### decapitalize - -Decapitalizes the first letter of a string. - -Use array destructuring and `String.toLowerCase()` to decapitalize first letter, `...rest` to get array of characters after first letter and then `Array.prototype.join('')` to make it a string again. -Omit the `upperRest` parameter to keep the rest of the string intact, or set it to `true` to convert to uppercase. - +### decapitalize + +Decapitalizes the first letter of a string. + +Use array destructuring and `String.toLowerCase()` to decapitalize first letter, `...rest` to get array of characters after first letter and then `Array.prototype.join('')` to make it a string again. +Omit the `upperRest` parameter to keep the rest of the string intact, or set it to `true` to convert to uppercase. + ```js const decapitalize = ([first, ...rest], upperRest = false) => first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); @@ -7863,18 +7885,18 @@ const decapitalize = ([first, ...rest], upperRest = false) => ```js decapitalize('FooBar'); // 'fooBar' decapitalize('FooBar', true); // 'fOOBAR' -``` +```
    [⬆ Back to top](#contents) -### escapeHTML - -Escapes a string for use in HTML. - -Use `String.prototype.replace()` with a regexp that matches the characters that need to be escaped, using a callback function to replace each character instance with its associated escaped character using a dictionary (object). - +### escapeHTML + +Escapes a string for use in HTML. + +Use `String.prototype.replace()` with a regexp that matches the characters that need to be escaped, using a callback function to replace each character instance with its associated escaped character using a dictionary (object). + ```js const escapeHTML = str => str.replace( @@ -7895,18 +7917,18 @@ const escapeHTML = str => ```js escapeHTML('Me & you'); // '<a href="#">Me & you</a>' -``` +```
    [⬆ Back to top](#contents) -### escapeRegExp - -Escapes a string to use in a regular expression. - -Use `String.prototype.replace()` to escape special characters. - +### escapeRegExp + +Escapes a string to use in a regular expression. + +Use `String.prototype.replace()` to escape special characters. + ```js const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); ``` @@ -7916,19 +7938,19 @@ const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); ```js escapeRegExp('(test)'); // \\(test\\) -``` +```
    [⬆ Back to top](#contents) -### fromCamelCase - -Converts a string from camelcase. - -Use `String.prototype.replace()` to remove underscores, hyphens, and spaces and convert words to camelcase. -Omit the second argument to use a default `separator` of `_`. - +### fromCamelCase + +Converts a string from camelcase. + +Use `String.prototype.replace()` to remove underscores, hyphens, and spaces and convert words to camelcase. +Omit the second argument to use a default `separator` of `_`. + ```js const fromCamelCase = (str, separator = '_') => str @@ -7944,19 +7966,19 @@ const fromCamelCase = (str, separator = '_') => fromCamelCase('someDatabaseFieldName', ' '); // 'some database field name' fromCamelCase('someLabelThatNeedsToBeCamelized', '-'); // 'some-label-that-needs-to-be-camelized' fromCamelCase('someJavascriptProperty', '_'); // 'some_javascript_property' -``` +```
    [⬆ Back to top](#contents) -### indentString - -Indents each line in the provided string. - -Use `String.replace` and a regular expression to add the character specified by `indent` `count` times at the start of each line. -Omit the third parameter, `indent`, to use a default indentation character of `' '`. - +### indentString + +Indents each line in the provided string. + +Use `String.replace` and a regular expression to add the character specified by `indent` `count` times at the start of each line. +Omit the third parameter, `indent`, to use a default indentation character of `' '`. + ```js const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); ``` @@ -7967,18 +7989,18 @@ const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.rep ```js indentString('Lorem\nIpsum', 2); // ' Lorem\n Ipsum' indentString('Lorem\nIpsum', 2, '_'); // '__Lorem\n__Ipsum' -``` +```
    [⬆ Back to top](#contents) -### isAbsoluteURL - -Returns `true` if the given string is an absolute URL, `false` otherwise. - -Use a regular expression to test if the string is an absolute URL. - +### isAbsoluteURL + +Returns `true` if the given string is an absolute URL, `false` otherwise. + +Use a regular expression to test if the string is an absolute URL. + ```js const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); ``` @@ -7990,18 +8012,18 @@ const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); isAbsoluteURL('https://google.com'); // true isAbsoluteURL('ftp://www.myserver.net'); // true isAbsoluteURL('/foo/bar'); // false -``` +```
    [⬆ Back to top](#contents) -### isAnagram - -Checks if a string is an anagram of another string (case-insensitive, ignores spaces, punctuation and special characters). - -Use `String.toLowerCase()`, `String.prototype.replace()` with an appropriate regular expression to remove unnecessary characters, `String.prototype.split('')`, `Array.prototype.sort()` and `Array.prototype.join('')` on both strings to normalize them, then check if their normalized forms are equal. - +### isAnagram + +Checks if a string is an anagram of another string (case-insensitive, ignores spaces, punctuation and special characters). + +Use `String.toLowerCase()`, `String.prototype.replace()` with an appropriate regular expression to remove unnecessary characters, `String.prototype.split('')`, `Array.prototype.sort()` and `Array.prototype.join('')` on both strings to normalize them, then check if their normalized forms are equal. + ```js const isAnagram = (str1, str2) => { const normalize = str => @@ -8020,18 +8042,18 @@ const isAnagram = (str1, str2) => { ```js isAnagram('iceman', 'cinema'); // true -``` +```
    [⬆ Back to top](#contents) -### isLowerCase - -Checks if a string is lower case. - -Convert the given string to lower case, using `String.toLowerCase()` and compare it to the original. - +### isLowerCase + +Checks if a string is lower case. + +Convert the given string to lower case, using `String.toLowerCase()` and compare it to the original. + ```js const isLowerCase = str => str === str.toLowerCase(); ``` @@ -8043,19 +8065,19 @@ const isLowerCase = str => str === str.toLowerCase(); isLowerCase('abc'); // true isLowerCase('a3@$'); // true isLowerCase('Ab4'); // false -``` +```
    [⬆ Back to top](#contents) -### isUpperCase - -Checks if a string is upper case. - -Convert the given string to upper case, using `String.prototype.toUpperCase()` and compare it to the original. - - +### isUpperCase + +Checks if a string is upper case. + +Convert the given string to upper case, using `String.prototype.toUpperCase()` and compare it to the original. + + ```js const isUpperCase = str => str === str.toUpperCase(); ``` @@ -8067,20 +8089,20 @@ const isUpperCase = str => str === str.toUpperCase(); isUpperCase('ABC'); // true isLowerCase('A3@$'); // true isLowerCase('aB4'); // false -``` +```
    [⬆ Back to top](#contents) -### mapString - -Creates a new string with the results of calling a provided function on every character in the calling string. - -Use `String.prototype.split('')` and `Array.prototype.map()` to call the provided function, `fn`, for each character in `str`. -Use `Array.prototype.join('')` to recombine the array of characters into a string. -The callback function, `fn`, takes three arguments (the current character, the index of the current character and the string `mapString` was called upon). - +### mapString + +Creates a new string with the results of calling a provided function on every character in the calling string. + +Use `String.prototype.split('')` and `Array.prototype.map()` to call the provided function, `fn`, for each character in `str`. +Use `Array.prototype.join('')` to recombine the array of characters into a string. +The callback function, `fn`, takes three arguments (the current character, the index of the current character and the string `mapString` was called upon). + ```js const mapString = (str, fn) => str @@ -8094,20 +8116,20 @@ const mapString = (str, fn) => ```js mapString('lorem ipsum', c => c.toUpperCase()); // 'LOREM IPSUM' -``` +```
    [⬆ Back to top](#contents) -### mask - -Replaces all but the last `num` of characters with the specified mask character. - -Use `String.prototype.slice()` to grab the portion of the characters that will remain unmasked and use `String.padStart()` to fill the beginning of the string with the mask character up to the original length. -Omit the second argument, `num`, to keep a default of `4` characters unmasked. If `num` is negative, the unmasked characters will be at the start of the string. -Omit the third argument, `mask`, to use a default character of `'*'` for the mask. - +### mask + +Replaces all but the last `num` of characters with the specified mask character. + +Use `String.prototype.slice()` to grab the portion of the characters that will remain unmasked and use `String.padStart()` to fill the beginning of the string with the mask character up to the original length. +Omit the second argument, `num`, to keep a default of `4` characters unmasked. If `num` is negative, the unmasked characters will be at the start of the string. +Omit the third argument, `mask`, to use a default character of `'*'` for the mask. + ```js const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); ``` @@ -8119,19 +8141,19 @@ const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.l mask(1234567890); // '******7890' mask(1234567890, 3); // '*******890' mask(1234567890, -4, '$'); // '$$$$567890' -``` +```
    [⬆ Back to top](#contents) -### pad - -Pads a string on both sides with the specified character, if it's shorter than the specified length. - -Use `String.padStart()` and `String.padEnd()` to pad both sides of the given string. -Omit the third argument, `char`, to use the whitespace character as the default padding character. - +### pad + +Pads a string on both sides with the specified character, if it's shorter than the specified length. + +Use `String.padStart()` and `String.padEnd()` to pad both sides of the given string. +Omit the third argument, `char`, to use the whitespace character as the default padding character. + ```js const pad = (str, length, char = ' ') => str.padStart((str.length + length) / 2, char).padEnd(length, char); @@ -8144,43 +8166,43 @@ const pad = (str, length, char = ' ') => pad('cat', 8); // ' cat ' pad(String(42), 6, '0'); // '004200' pad('foobar', 3); // 'foobar' -``` +```
    [⬆ Back to top](#contents) -### palindrome - -Returns `true` if the given string is a palindrome, `false` otherwise. - -Convert the string to `String.prototype.toLowerCase()` and use `String.prototype.replace()` to remove non-alphanumeric characters from it. -Then, use the spread operator (`...`) to split the string into individual characters, `Array.prototype.reverse()`, `String.prototype.join('')` and compare it to the original, unreversed string, after converting it to `String.prototype.toLowerCase()`. - +### palindrome + +Returns `true` if the given string is a palindrome, `false` otherwise. + +Convert the string to `String.prototype.toLowerCase()` and use `String.prototype.replace()` to remove non-alphanumeric characters from it. +Then, use the spread operator (`...`) to split the string into individual characters, `Array.prototype.reverse()`, `String.prototype.join('')` and compare it to the original, unreversed string, after converting it to `String.prototype.toLowerCase()`. + ```js -const palindrome = str => { - const s = str.toLowerCase().replace(/[\W_]/g, ''); - return s === [...s].reverse().join(''); -}; +const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g, ''); + return s === [...s].reverse().join(''); +}; ```
    Examples ```js -palindrome('taco cat'); // true -``` +palindrome('taco cat'); // true +```

    [⬆ Back to top](#contents) -### pluralize - -Returns the singular or plural form of the word based on the input number. If the first argument is an `object`, it will use a closure by returning a function that can auto-pluralize words that don't simply end in `s` if the supplied dictionary contains the word. - -If `num` is either `-1` or `1`, return the singular form of the word. If `num` is any other number, return the plural form. Omit the third argument to use the default of the singular word + `s`, or supply a custom pluralized word when necessary. If the first argument is an `object`, utilize a closure by returning a function which can use the supplied dictionary to resolve the correct plural form of the word. - +### pluralize + +Returns the singular or plural form of the word based on the input number. If the first argument is an `object`, it will use a closure by returning a function that can auto-pluralize words that don't simply end in `s` if the supplied dictionary contains the word. + +If `num` is either `-1` or `1`, return the singular form of the word. If `num` is any other number, return the plural form. Omit the third argument to use the default of the singular word + `s`, or supply a custom pluralized word when necessary. If the first argument is an `object`, utilize a closure by returning a function which can use the supplied dictionary to resolve the correct plural form of the word. + ```js const pluralize = (val, word, plural = word + 's') => { const _pluralize = (num, word, plural = word + 's') => @@ -8205,18 +8227,18 @@ const PLURALS = { }; const autoPluralize = pluralize(PLURALS); autoPluralize(2, 'person'); // 'people' -``` +```
    [⬆ Back to top](#contents) -### removeNonASCII - -Removes non-printable ASCII characters. - -Use a regular expression to remove non-printable ASCII characters. - +### removeNonASCII + +Removes non-printable ASCII characters. + +Use a regular expression to remove non-printable ASCII characters. + ```js const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); ``` @@ -8226,19 +8248,19 @@ const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); ```js removeNonASCII('äÄçÇéÉêlorem-ipsumöÖÐþúÚ'); // 'lorem-ipsum' -``` +```
    [⬆ Back to top](#contents) -### reverseString - -Reverses a string. - -Use the spread operator (`...`) and `Array.prototype.reverse()` to reverse the order of the characters in the string. -Combine characters to get a string using `String.prototype.join('')`. - +### reverseString + +Reverses a string. + +Use the spread operator (`...`) and `Array.prototype.reverse()` to reverse the order of the characters in the string. +Combine characters to get a string using `String.prototype.join('')`. + ```js const reverseString = str => [...str].reverse().join(''); ``` @@ -8248,18 +8270,18 @@ const reverseString = str => [...str].reverse().join(''); ```js reverseString('foobar'); // 'raboof' -``` +```
    [⬆ Back to top](#contents) -### sortCharactersInString - -Alphabetically sorts the characters in a string. - -Use the spread operator (`...`), `Array.prototype.sort()` and `String.localeCompare()` to sort the characters in `str`, recombine using `String.prototype.join('')`. - +### sortCharactersInString + +Alphabetically sorts the characters in a string. + +Use the spread operator (`...`), `Array.prototype.sort()` and `String.localeCompare()` to sort the characters in `str`, recombine using `String.prototype.join('')`. + ```js const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); ``` @@ -8269,18 +8291,18 @@ const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b) ```js sortCharactersInString('cabbage'); // 'aabbceg' -``` +```
    [⬆ Back to top](#contents) -### splitLines - -Splits a multiline string into an array of lines. - -Use `String.prototype.split()` and a regular expression to match line breaks and create an array. - +### splitLines + +Splits a multiline string into an array of lines. + +Use `String.prototype.split()` and a regular expression to match line breaks and create an array. + ```js const splitLines = str => str.split(/\r?\n/); ``` @@ -8290,7 +8312,7 @@ const splitLines = str => str.split(/\r?\n/); ```js splitLines('This\nis a\nmultiline\nstring.\n'); // ['This', 'is a', 'multiline', 'string.' , ''] -``` +``` @@ -8331,12 +8353,12 @@ stringPermutations('abc'); // ['abc','acb','bac','bca','cab','cba']
    [⬆ Back to top](#contents) -### stripHTMLTags - -Removes HTML/XML tags from string. - -Use a regular expression to remove HTML/XML tags from a string. - +### stripHTMLTags + +Removes HTML/XML tags from string. + +Use a regular expression to remove HTML/XML tags from a string. + ```js const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); ``` @@ -8346,18 +8368,18 @@ const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); ```js stripHTMLTags('

    lorem ipsum

    '); // 'lorem ipsum' -``` +```
    [⬆ Back to top](#contents) -### toCamelCase - -Converts a string to camelcase. - -Break the string into words and combine them capitalizing the first letter of each word, using a regexp. - +### toCamelCase + +Converts a string to camelcase. + +Break the string into words and combine them capitalizing the first letter of each word, using a regexp. + ```js const toCamelCase = str => { let s = @@ -8378,18 +8400,18 @@ toCamelCase('some_database_field_name'); // 'someDatabaseFieldName' toCamelCase('Some label that needs to be camelized'); // 'someLabelThatNeedsToBeCamelized' toCamelCase('some-javascript-property'); // 'someJavascriptProperty' toCamelCase('some-mixed_string with spaces_underscores-and-hyphens'); // 'someMixedStringWithSpacesUnderscoresAndHyphens' -``` +```
    [⬆ Back to top](#contents) -### toKebabCase - -Converts a string to kebab case. - -Break the string into words and combine them adding `-` as a separator, using a regexp. - +### toKebabCase + +Converts a string to kebab case. + +Break the string into words and combine them adding `-` as a separator, using a regexp. + ```js const toKebabCase = str => str && @@ -8408,18 +8430,18 @@ toKebabCase('some text'); // 'some-text' toKebabCase('some-mixed_string With spaces_underscores-and-hyphens'); // 'some-mixed-string-with-spaces-underscores-and-hyphens' toKebabCase('AllThe-small Things'); // "all-the-small-things" toKebabCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML'); // "i-am-listening-to-fm-while-loading-different-url-on-my-browser-and-also-editing-xml-and-html" -``` +```
    [⬆ Back to top](#contents) -### toSnakeCase - -Converts a string to snake case. - -Break the string into words and combine them adding `_` as a separator, using a regexp. - +### toSnakeCase + +Converts a string to snake case. + +Break the string into words and combine them adding `_` as a separator, using a regexp. + ```js const toSnakeCase = str => str && @@ -8438,47 +8460,47 @@ toSnakeCase('some text'); // 'some_text' toSnakeCase('some-mixed_string With spaces_underscores-and-hyphens'); // 'some_mixed_string_with_spaces_underscores_and_hyphens' toSnakeCase('AllThe-small Things'); // "all_the_smal_things" toSnakeCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML'); // "i_am_listening_to_fm_while_loading_different_url_on_my_browser_and_also_editing_some_xml_and_html" -``` +```
    [⬆ Back to top](#contents) -### toTitleCase - -Converts a string to title case. - -Break the string into words, using a regexp, and combine them capitalizing the first letter of each word and adding a whitespace between them. - +### toTitleCase + +Converts a string to title case. + +Break the string into words, using a regexp, and combine them capitalizing the first letter of each word and adding a whitespace between them. + ```js -const toTitleCase = str => - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.charAt(0).toUpperCase() + x.slice(1)) - .join(' '); +const toTitleCase = str => + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.charAt(0).toUpperCase() + x.slice(1)) + .join(' '); ```
    Examples ```js -toTitleCase('some_database_field_name'); // 'Some Database Field Name' -toTitleCase('Some label that needs to be title-cased'); // 'Some Label That Needs To Be Title Cased' -toTitleCase('some-package-name'); // 'Some Package Name' -toTitleCase('some-mixed_string with spaces_underscores-and-hyphens'); // 'Some Mixed String With Spaces Underscores And Hyphens' -``` +toTitleCase('some_database_field_name'); // 'Some Database Field Name' +toTitleCase('Some label that needs to be title-cased'); // 'Some Label That Needs To Be Title Cased' +toTitleCase('some-package-name'); // 'Some Package Name' +toTitleCase('some-mixed_string with spaces_underscores-and-hyphens'); // 'Some Mixed String With Spaces Underscores And Hyphens' +```

    [⬆ Back to top](#contents) -### truncateString - -Truncates a string up to a specified length. - -Determine if the string's `length` is greater than `num`. -Return the string truncated to the desired length, with `'...'` appended to the end or the original string. - +### truncateString + +Truncates a string up to a specified length. + +Determine if the string's `length` is greater than `num`. +Return the string truncated to the desired length, with `'...'` appended to the end or the original string. + ```js const truncateString = (str, num) => str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; @@ -8489,18 +8511,18 @@ const truncateString = (str, num) => ```js truncateString('boomerang', 7); // 'boom...' -``` +```
    [⬆ Back to top](#contents) -### unescapeHTML - -Unescapes escaped HTML characters. - -Use `String.prototype.replace()` with a regex that matches the characters that need to be unescaped, using a callback function to replace each escaped character instance with its associated unescaped character using a dictionary (object). - +### unescapeHTML + +Unescapes escaped HTML characters. + +Use `String.prototype.replace()` with a regex that matches the characters that need to be unescaped, using a callback function to replace each escaped character instance with its associated unescaped character using a dictionary (object). + ```js const unescapeHTML = str => str.replace( @@ -8521,7 +8543,7 @@ const unescapeHTML = str => ```js unescapeHTML('<a href="#">Me & you</a>'); // 'Me & you' -``` +``` @@ -8556,13 +8578,13 @@ URLJoin('http://www.google.com', 'a', '/b/cd', '?foo=123', '?bar=foo'); // 'http
    [⬆ Back to top](#contents) -### words - -Converts a given string into an array of words. - -Use `String.prototype.split()` with a supplied pattern (defaults to non-alpha as a regexp) to convert to an array of strings. Use `Array.prototype.filter()` to remove any empty strings. -Omit the second argument to use the default regexp. - +### words + +Converts a given string into an array of words. + +Use `String.prototype.split()` with a supplied pattern (defaults to non-alpha as a regexp) to convert to an array of strings. Use `Array.prototype.filter()` to remove any empty strings. +Omit the second argument to use the default regexp. + ```js const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); ``` @@ -8573,7 +8595,7 @@ const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolea ```js words('I love javaScript!!'); // ["I", "love", "javaScript"] words('python, javaScript & coffee'); // ["python", "javaScript", "coffee"] -``` +``` @@ -8584,12 +8606,12 @@ words('python, javaScript & coffee'); // ["python", "javaScript", "coffee"] ## 📃 Type -### getType - -Returns the native type of a value. - -Returns lowercased constructor name of value, `"undefined"` or `"null"` if value is `undefined` or `null`. - +### getType + +Returns the native type of a value. + +Returns lowercased 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(); @@ -8600,18 +8622,18 @@ const getType = v => ```js getType(new Set([1, 2, 3])); // 'set' -``` +```
    [⬆ Back to top](#contents) -### is - -Checks if the provided value is of the specified type. - -Ensure the value is not `undefined` or `null` using `Array.prototype.includes()`, and compare the `constructor` property on the value with `type` to check if the provided value is of the specified `type`. - +### is + +Checks if the provided value is of the specified type. + +Ensure the value is not `undefined` or `null` using `Array.prototype.includes()`, and compare the `constructor` property on the value with `type` to check if the provided value is of the specified `type`. + ```js const is = (type, val) => ![, null].includes(val) && val.constructor === type; ``` @@ -8633,18 +8655,18 @@ is(Number, 1); // true is(Number, new Number(1)); // true is(Boolean, true); // true is(Boolean, new Boolean(true)); // true -``` +```
    [⬆ Back to top](#contents) -### isArrayLike - -Checks if the provided argument is array-like (i.e. is iterable). - -Check if the provided argument is not `null` and that its `Symbol.iterator` property is a function. - +### isArrayLike + +Checks if the provided argument is array-like (i.e. is iterable). + +Check if the provided argument is not `null` and that its `Symbol.iterator` property is a function. + ```js const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; ``` @@ -8656,18 +8678,18 @@ const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'funct isArrayLike(document.querySelectorAll('.className')); // true isArrayLike('abc'); // true isArrayLike(null); // false -``` +```
    [⬆ Back to top](#contents) -### isBoolean - -Checks if the given argument is a native boolean element. - -Use `typeof` to check if a value is classified as a boolean primitive. - +### isBoolean + +Checks if the given argument is a native boolean element. + +Use `typeof` to check if a value is classified as a boolean primitive. + ```js const isBoolean = val => typeof val === 'boolean'; ``` @@ -8678,18 +8700,18 @@ const isBoolean = val => typeof val === 'boolean'; ```js isBoolean(null); // false isBoolean(false); // true -``` +```
    [⬆ Back to top](#contents) -### isEmpty - -Returns true if the a value is an empty object, collection, map or set, has no enumerable properties or is any type that is not considered a collection. - -Check if the provided value is `null` or if its `length` is equal to `0`. - +### isEmpty + +Returns true if the a value is an empty object, collection, map or set, has no enumerable properties or is any type that is not considered a collection. + +Check if the provided value is `null` or if its `length` is equal to `0`. + ```js const isEmpty = val => val == null || !(Object.keys(val) || val).length; ``` @@ -8708,18 +8730,18 @@ isEmpty({ a: 1, b: 2 }); // false isEmpty('text'); // false isEmpty(123); // true - type is not considered a collection isEmpty(true); // true - type is not considered a collection -``` +```
    [⬆ Back to top](#contents) -### isFunction - -Checks if the given argument is a function. - -Use `typeof` to check if a value is classified as a function primitive. - +### isFunction + +Checks if the given argument is a function. + +Use `typeof` to check if a value is classified as a function primitive. + ```js const isFunction = val => typeof val === 'function'; ``` @@ -8730,18 +8752,18 @@ const isFunction = val => typeof val === 'function'; ```js isFunction('x'); // false isFunction(x => x); // true -``` +```
    [⬆ Back to top](#contents) -### isNil - -Returns `true` if the specified value is `null` or `undefined`, `false` otherwise. - -Use the strict equality operator to check if the value and of `val` are equal to `null` or `undefined`. - +### isNil + +Returns `true` if the specified value is `null` or `undefined`, `false` otherwise. + +Use the strict equality operator to check if the value and of `val` are equal to `null` or `undefined`. + ```js const isNil = val => val === undefined || val === null; ``` @@ -8752,18 +8774,18 @@ const isNil = val => val === undefined || val === null; ```js isNil(null); // true isNil(undefined); // true -``` +```
    [⬆ Back to top](#contents) -### isNull - -Returns `true` if the specified value is `null`, `false` otherwise. - -Use the strict equality operator to check if the value and of `val` are equal to `null`. - +### isNull + +Returns `true` if the specified value is `null`, `false` otherwise. + +Use the strict equality operator to check if the value and of `val` are equal to `null`. + ```js const isNull = val => val === null; ``` @@ -8773,18 +8795,18 @@ const isNull = val => val === null; ```js isNull(null); // true -``` +```
    [⬆ Back to top](#contents) -### isNumber - -Checks if the given argument is a number. - -Use `typeof` to check if a value is classified as a number primitive. - +### isNumber + +Checks if the given argument is a number. + +Use `typeof` to check if a value is classified as a number primitive. + ```js const isNumber = val => typeof val === 'number'; ``` @@ -8795,19 +8817,19 @@ const isNumber = val => typeof val === 'number'; ```js isNumber('1'); // false isNumber(1); // true -``` +```
    [⬆ Back to top](#contents) -### isObject - -Returns a boolean determining if the passed value is an object or not. - -Uses the `Object` constructor to create an object wrapper for the given value. -If the value is `null` or `undefined`, create and return an empty object. Οtherwise, return an object of a type that corresponds to the given value. - +### isObject + +Returns a boolean determining if the passed value is an object or not. + +Uses the `Object` constructor to create an object wrapper for the given value. +If the value is `null` or `undefined`, create and return an empty object. Οtherwise, return an object of a type that corresponds to the given value. + ```js const isObject = obj => obj === Object(obj); ``` @@ -8822,18 +8844,18 @@ isObject(['Hello!']); // true isObject({ a: 1 }); // true isObject({}); // true isObject(true); // false -``` +```
    [⬆ Back to top](#contents) -### isObjectLike - -Checks if a value is object-like. - -Check if the provided value is not `null` and its `typeof` is equal to `'object'`. - +### isObjectLike + +Checks if a value is object-like. + +Check if the provided value is not `null` and its `typeof` is equal to `'object'`. + ```js const isObjectLike = val => val !== null && typeof val === 'object'; ``` @@ -8846,18 +8868,18 @@ isObjectLike({}); // true isObjectLike([1, 2, 3]); // true isObjectLike(x => x); // false isObjectLike(null); // false -``` +```
    [⬆ Back to top](#contents) -### isPlainObject - -Checks if the provided value is an object created by the Object constructor. - -Check if the provided value is truthy, use `typeof` to check if it is an object and `Object.constructor` to make sure the constructor is equal to `Object`. - +### isPlainObject + +Checks if the provided value is an object created by the Object constructor. + +Check if the provided value is truthy, use `typeof` to check if it is an object and `Object.constructor` to make sure the constructor is equal to `Object`. + ```js const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; ``` @@ -8868,44 +8890,44 @@ const isPlainObject = val => !!val && typeof val === 'object' && val.constructor ```js isPlainObject({ a: 1 }); // true isPlainObject(new Map()); // false -``` +```
    [⬆ Back to top](#contents) -### isPrimitive - -Returns a boolean determining if the passed value is primitive or not. - -Create an object from `val` and compare it with `val` to determine if the passed value is primitive (i.e. not equal to the created object). - +### isPrimitive + +Returns a boolean determining if the passed value is primitive or not. + +Create an object from `val` and compare it with `val` to determine if the passed value is primitive (i.e. not equal to the created object). + ```js -const isPrimitive = val => Object(val) !== val; +const isPrimitive = val => Object(val) !== val; ```
    Examples ```js -isPrimitive(null); // true -isPrimitive(50); // true -isPrimitive('Hello!'); // true -isPrimitive(false); // true -isPrimitive(Symbol()); // true -isPrimitive([]); // false -``` +isPrimitive(null); // true +isPrimitive(50); // true +isPrimitive('Hello!'); // true +isPrimitive(false); // true +isPrimitive(Symbol()); // true +isPrimitive([]); // false +```

    [⬆ Back to top](#contents) -### isPromiseLike - -Returns `true` if an object looks like a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), `false` otherwise. - -Check if the object is not `null`, its `typeof` matches either `object` or `function` and if it has a `.then` property, which is also a `function`. - +### isPromiseLike + +Returns `true` if an object looks like a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), `false` otherwise. + +Check if the object is not `null`, its `typeof` matches either `object` or `function` and if it has a `.then` property, which is also a `function`. + ```js const isPromiseLike = obj => obj !== null && @@ -8924,39 +8946,39 @@ isPromiseLike({ }); // true isPromiseLike(null); // false isPromiseLike({}); // false -``` +```
    [⬆ Back to top](#contents) -### isString - -Checks if the given argument is a string. Only works for string primitives. - -Use `typeof` to check if a value is classified as a string primitive. - +### isString + +Checks if the given argument is a string. Only works for string primitives. + +Use `typeof` to check if a value is classified as a string primitive. + ```js -const isString = val => typeof val === 'string'; +const isString = val => typeof val === 'string'; ```
    Examples ```js -isString('10'); // true -``` +isString('10'); // true +```

    [⬆ Back to top](#contents) -### isSymbol - -Checks if the given argument is a symbol. - -Use `typeof` to check if a value is classified as a symbol primitive. - +### isSymbol + +Checks if the given argument is a symbol. + +Use `typeof` to check if a value is classified as a symbol primitive. + ```js const isSymbol = val => typeof val === 'symbol'; ``` @@ -8966,18 +8988,18 @@ const isSymbol = val => typeof val === 'symbol'; ```js isSymbol(Symbol('x')); // true -``` +```
    [⬆ Back to top](#contents) -### isUndefined - -Returns `true` if the specified value is `undefined`, `false` otherwise. - -Use the strict equality operator to check if the value and of `val` are equal to `undefined`. - +### isUndefined + +Returns `true` if the specified value is `undefined`, `false` otherwise. + +Use the strict equality operator to check if the value and of `val` are equal to `undefined`. + ```js const isUndefined = val => val === undefined; ``` @@ -8987,37 +9009,37 @@ const isUndefined = val => val === undefined; ```js isUndefined(undefined); // true -``` +```
    [⬆ Back to top](#contents) -### isValidJSON - -Checks if the provided string is a valid JSON. - -Use `JSON.parse()` and a `try... catch` block to check if the provided string is a valid JSON. - +### isValidJSON + +Checks if the provided string is a valid JSON. + +Use `JSON.parse()` and a `try... catch` block to check if the provided string is a valid JSON. + ```js -const isValidJSON = str => { - try { - JSON.parse(str); - return true; - } catch (e) { - return false; - } -}; +const isValidJSON = str => { + try { + JSON.parse(str); + return true; + } catch (e) { + return false; + } +}; ```
    Examples ```js -isValidJSON('{"name":"Adam","age":20}'); // true -isValidJSON('{"name":"Adam",age:"20"}'); // false -isValidJSON(null); // true -``` +isValidJSON('{"name":"Adam","age":20}'); // true +isValidJSON('{"name":"Adam",age:"20"}'); // false +isValidJSON(null); // true +```
    @@ -9028,12 +9050,12 @@ isValidJSON(null); // true ## 🔧 Utility -### castArray - -Casts the provided value as an array if it's not one. - -Use `Array.prototype.isArray()` to determine if `val` is an array and return it as-is or encapsulated in an array accordingly. - +### castArray + +Casts the provided value as an array if it's not one. + +Use `Array.prototype.isArray()` to determine if `val` is an array and return it as-is or encapsulated in an array accordingly. + ```js const castArray = val => (Array.isArray(val) ? val : [val]); ``` @@ -9044,18 +9066,18 @@ const castArray = val => (Array.isArray(val) ? val : [val]); ```js castArray('foo'); // ['foo'] castArray([1]); // [1] -``` +```
    [⬆ Back to top](#contents) -### cloneRegExp - -Clones a regular expression. - -Use `new RegExp()`, `RegExp.source` and `RegExp.flags` to clone the given regular expression. - +### cloneRegExp + +Clones a regular expression. + +Use `new RegExp()`, `RegExp.source` and `RegExp.flags` to clone the given regular expression. + ```js const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); ``` @@ -9066,18 +9088,18 @@ const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); ```js const regExp = /lorem ipsum/gi; const regExp2 = cloneRegExp(regExp); // /lorem ipsum/gi -``` +```
    [⬆ Back to top](#contents) -### coalesce - -Returns the first non-null/undefined argument. - -Use `Array.prototype.find()` to return the first non `null`/`undefined` argument. - +### coalesce + +Returns the first non-null/undefined argument. + +Use `Array.prototype.find()` to return the first non `null`/`undefined` argument. + ```js const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); ``` @@ -9087,18 +9109,18 @@ const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); ```js coalesce(null, undefined, '', NaN, 'Waldo'); // "" -``` +```
    [⬆ Back to top](#contents) -### coalesceFactory - -Returns a customized coalesce function that returns the first argument that returns `true` from the provided argument validation function. - -Use `Array.prototype.find()` to return the first argument that returns `true` from the provided argument validation function. - +### coalesceFactory + +Returns a customized coalesce function that returns the first argument that returns `true` from the provided argument validation function. + +Use `Array.prototype.find()` to return the first argument that returns `true` from the provided argument validation function. + ```js const coalesceFactory = valid => (...args) => args.find(valid); ``` @@ -9109,19 +9131,19 @@ const coalesceFactory = valid => (...args) => args.find(valid); ```js const customCoalesce = coalesceFactory(_ => ![null, undefined, '', NaN].includes(_)); customCoalesce(undefined, null, NaN, '', 'Waldo'); // "Waldo" -``` +```
    [⬆ Back to top](#contents) -### extendHex - -Extends a 3-digit color code to a 6-digit color code. - -Use `Array.prototype.map()`, `String.prototype.split()` and `Array.prototype.join()` to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. -`Array.prototype.slice()` is used to remove `#` from string start since it's added once. - +### extendHex + +Extends a 3-digit color code to a 6-digit color code. + +Use `Array.prototype.map()`, `String.prototype.split()` and `Array.prototype.join()` to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. +`Array.prototype.slice()` is used to remove `#` from string start since it's added once. + ```js const extendHex = shortHex => '#' + @@ -9138,19 +9160,19 @@ const extendHex = shortHex => ```js extendHex('#03f'); // '#0033ff' extendHex('05a'); // '#0055aa' -``` +```
    [⬆ Back to top](#contents) -### getURLParameters - -Returns an object containing the parameters of the current URL. - -Use `String.match()` with an appropriate regular expression to get all key-value pairs, `Array.prototype.reduce()` to map and combine them into a single object. -Pass `location.search` as the argument to apply to the current `url`. - +### getURLParameters + +Returns an object containing the parameters of the current URL. + +Use `String.match()` with an appropriate regular expression to get all key-value pairs, `Array.prototype.reduce()` to map and combine them into a single object. +Pass `location.search` as the argument to apply to the current `url`. + ```js const getURLParameters = url => (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( @@ -9165,7 +9187,7 @@ const getURLParameters = url => ```js getURLParameters('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'} getURLParameters('google.com'); // {} -``` +``` @@ -9212,114 +9234,114 @@ hexToRGB('#fff'); // 'rgb(255, 255, 255)'
    [⬆ Back to top](#contents) -### httpGet - -Makes a `GET` request to the passed URL. - -Use [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) web api to make a `get` request to the given `url`. -Handle the `onload` event, by calling the given `callback` the `responseText`. -Handle the `onerror` event, by running the provided `err` function. -Omit the third argument, `err`, to log errors to the console's `error` stream by default. - +### httpGet + +Makes a `GET` request to the passed URL. + +Use [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) web api to make a `get` request to the given `url`. +Handle the `onload` event, by calling the given `callback` the `responseText`. +Handle the `onerror` event, by running the provided `err` function. +Omit the third argument, `err`, to log errors to the console's `error` stream by default. + ```js -const httpGet = (url, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('GET', url, true); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(); -}; +const httpGet = (url, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('GET', url, true); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(); +}; ```
    Examples ```js -httpGet( - 'https://jsonplaceholder.typicode.com/posts/1', - console.log -); /* -Logs: { - "userId": 1, - "id": 1, - "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", - "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" -} -*/ -``` +httpGet( + 'https://jsonplaceholder.typicode.com/posts/1', + console.log +); /* +Logs: { + "userId": 1, + "id": 1, + "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", + "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" +} +*/ +```

    [⬆ Back to top](#contents) -### httpPost - -Makes a `POST` request to the passed URL. - -Use [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) web api to make a `post` request to the given `url`. -Set the value of an `HTTP` request header with `setRequestHeader` method. -Handle the `onload` event, by calling the given `callback` the `responseText`. -Handle the `onerror` event, by running the provided `err` function. -Omit the third argument, `data`, to send no data to the provided `url`. -Omit the fourth argument, `err`, to log errors to the console's `error` stream by default. - +### httpPost + +Makes a `POST` request to the passed URL. + +Use [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) web api to make a `post` request to the given `url`. +Set the value of an `HTTP` request header with `setRequestHeader` method. +Handle the `onload` event, by calling the given `callback` the `responseText`. +Handle the `onerror` event, by running the provided `err` function. +Omit the third argument, `data`, to send no data to the provided `url`. +Omit the fourth argument, `err`, to log errors to the console's `error` stream by default. + ```js -const httpPost = (url, data, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('POST', url, true); - request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(data); -}; +const httpPost = (url, data, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('POST', url, true); + request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(data); +}; ```
    Examples ```js -const newPost = { - userId: 1, - id: 1337, - title: 'Foo', - body: 'bar bar bar' -}; -const data = JSON.stringify(newPost); -httpPost( - 'https://jsonplaceholder.typicode.com/posts', - data, - console.log -); /* -Logs: { - "userId": 1, - "id": 1337, - "title": "Foo", - "body": "bar bar bar" -} -*/ -httpPost( - 'https://jsonplaceholder.typicode.com/posts', - null, // does not send a body - console.log -); /* -Logs: { - "id": 101 -} -*/ -``` +const newPost = { + userId: 1, + id: 1337, + title: 'Foo', + body: 'bar bar bar' +}; +const data = JSON.stringify(newPost); +httpPost( + 'https://jsonplaceholder.typicode.com/posts', + data, + console.log +); /* +Logs: { + "userId": 1, + "id": 1337, + "title": "Foo", + "body": "bar bar bar" +} +*/ +httpPost( + 'https://jsonplaceholder.typicode.com/posts', + null, // does not send a body + console.log +); /* +Logs: { + "id": 101 +} +*/ +```

    [⬆ Back to top](#contents) -### isBrowser - -Determines if the current runtime environment is a browser so that front-end modules can run on the server (Node) without throwing errors. - -Use `Array.prototype.includes()` on the `typeof` values of both `window` and `document` (globals usually only available in a browser environment unless they were explicitly defined), which will return `true` if one of them is `undefined`. -`typeof` allows globals to be checked for existence without throwing a `ReferenceError`. -If both of them are not `undefined`, then the current environment is assumed to be a browser. - +### isBrowser + +Determines if the current runtime environment is a browser so that front-end modules can run on the server (Node) without throwing errors. + +Use `Array.prototype.includes()` on the `typeof` values of both `window` and `document` (globals usually only available in a browser environment unless they were explicitly defined), which will return `true` if one of them is `undefined`. +`typeof` allows globals to be checked for existence without throwing a `ReferenceError`. +If both of them are not `undefined`, then the current environment is assumed to be a browser. + ```js const isBrowser = () => ![typeof window, typeof document].includes('undefined'); ``` @@ -9330,20 +9352,20 @@ const isBrowser = () => ![typeof window, typeof document].includes('undefined'); ```js isBrowser(); // true (browser) isBrowser(); // false (Node) -``` +```
    [⬆ Back to top](#contents) -### mostPerformant - -Returns the index of the function in an array of functions which executed the fastest. - -Use `Array.prototype.map()` to generate an array where each value is the total time taken to execute the function after `iterations` times. Use the difference in `performance.now()` values before and after to get the total time in milliseconds to a high degree of accuracy. -Use `Math.min()` to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. -Omit the second argument, `iterations`, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take. - +### mostPerformant + +Returns the index of the function in an array of functions which executed the fastest. + +Use `Array.prototype.map()` to generate an array where each value is the total time taken to execute the function after `iterations` times. Use the difference in `performance.now()` values before and after to get the total time in milliseconds to a high degree of accuracy. +Use `Math.min()` to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. +Omit the second argument, `iterations`, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take. + ```js const mostPerformant = (fns, iterations = 10000) => { const times = fns.map(fn => { @@ -9369,18 +9391,18 @@ mostPerformant([ [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number'); } ]); // 1 -``` +```
    [⬆ Back to top](#contents) -### nthArg - -Creates a function that gets the argument at index `n`. If `n` is negative, the nth argument from the end is returned. - -Use `Array.prototype.slice()` to get the desired argument at index `n`. - +### nthArg + +Creates a function that gets the argument at index `n`. If `n` is negative, the nth argument from the end is returned. + +Use `Array.prototype.slice()` to get the desired argument at index `n`. + ```js const nthArg = n => (...args) => args.slice(n)[0]; ``` @@ -9394,20 +9416,20 @@ third(1, 2, 3); // 3 third(1, 2); // undefined const last = nthArg(-1); last(1, 2, 3, 4, 5); // 5 -``` +```
    [⬆ Back to top](#contents) -### parseCookie - -Parse an HTTP Cookie header string and return an object of all cookie name-value pairs. - -Use `String.prototype.split(';')` to separate key-value pairs from each other. -Use `Array.prototype.map()` and `String.prototype.split('=')` to separate keys from values in each pair. -Use `Array.prototype.reduce()` and `decodeURIComponent()` to create an object with all key-value pairs. - +### parseCookie + +Parse an HTTP Cookie header string and return an object of all cookie name-value pairs. + +Use `String.prototype.split(';')` to separate key-value pairs from each other. +Use `Array.prototype.map()` and `String.prototype.split('=')` to separate keys from values in each pair. +Use `Array.prototype.reduce()` and `decodeURIComponent()` to create an object with all key-value pairs. + ```js const parseCookie = str => str @@ -9424,7 +9446,7 @@ const parseCookie = str => ```js parseCookie('foo=bar; equation=E%3Dmc%5E2'); // { foo: 'bar', equation: 'E=mc^2' } -``` +``` @@ -9463,12 +9485,12 @@ prettyBytes(123456789, 3, false); // "123MB"
    [⬆ Back to top](#contents) -### randomHexColorCode - -Generates a random hexadecimal color code. - -Use `Math.random` to generate a random 24-bit(6x4bits) hexadecimal number. Use bit shifting and then convert it to an hexadecimal String using `toString(16)`. - +### randomHexColorCode + +Generates a random hexadecimal color code. + +Use `Math.random` to generate a random 24-bit(6x4bits) hexadecimal number. Use bit shifting and then convert it to an hexadecimal String using `toString(16)`. + ```js const randomHexColorCode = () => { let n = (Math.random() * 0xfffff * 1000000).toString(16); @@ -9481,18 +9503,18 @@ const randomHexColorCode = () => { ```js randomHexColorCode(); // "#e34155" -``` +```
    [⬆ Back to top](#contents) -### RGBToHex - -Converts the values of RGB components to a color code. - -Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (`<<`) and `toString(16)`, then `String.padStart(6,'0')` to get a 6-digit hexadecimal value. - +### RGBToHex + +Converts the values of RGB components to a color code. + +Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (`<<`) and `toString(16)`, then `String.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'); ``` @@ -9502,18 +9524,18 @@ const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6 ```js RGBToHex(255, 165, 1); // 'ffa501' -``` +```
    [⬆ Back to top](#contents) -### serializeCookie - -Serialize a cookie name-value pair into a Set-Cookie header string. - -Use template literals and `encodeURIComponent()` to create the appropriate string. - +### serializeCookie + +Serialize a cookie name-value pair into a Set-Cookie header string. + +Use template literals and `encodeURIComponent()` to create the appropriate string. + ```js const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; ``` @@ -9523,18 +9545,18 @@ const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIC ```js serializeCookie('foo', 'bar'); // 'foo=bar' -``` +```
    [⬆ Back to top](#contents) -### timeTaken - -Measures the time taken by a function to execute. - -Use `console.time()` and `console.timeEnd()` to measure the difference between the start and end times to determine how long the callback took to execute. - +### timeTaken + +Measures the time taken by a function to execute. + +Use `console.time()` and `console.timeEnd()` to measure the difference between the start and end times to determine how long the callback took to execute. + ```js const timeTaken = callback => { console.time('timeTaken'); @@ -9549,18 +9571,18 @@ const timeTaken = callback => { ```js timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms -``` +```
    [⬆ Back to top](#contents) -### toCurrency - -Take a number and return specified currency formatting. - -Use `Intl.NumberFormat` to enable country / currency sensitive formatting. - +### toCurrency + +Take a number and return specified currency formatting. + +Use `Intl.NumberFormat` to enable country / currency sensitive formatting. + ```js const toCurrency = (n, curr, LanguageFormat = undefined) => Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); @@ -9575,16 +9597,16 @@ toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79 | currency: US Dollar | toCurrency(123456.789, 'USD', 'fa'); // ۱۲۳٬۴۵۶٫۷۹ ؜$ | currency: US Dollar | currencyLangFormat: Farsi toCurrency(322342436423.2435, 'JPY'); // ¥322,342,436,423 | currency: Japanese Yen | currencyLangFormat: Local toCurrency(322342436423.2435, 'JPY', 'fi'); // 322 342 436 423 ¥ | currency: Japanese Yen | currencyLangFormat: Finnish -``` +```
    [⬆ Back to top](#contents) -### toDecimalMark - -Use `toLocaleString()` to convert a float-point arithmetic to the [Decimal mark](https://en.wikipedia.org/wiki/Decimal_mark) form. It makes a comma separated string from a number. - +### toDecimalMark + +Use `toLocaleString()` to convert a float-point arithmetic to the [Decimal mark](https://en.wikipedia.org/wiki/Decimal_mark) form. It makes a comma separated string from a number. + ```js const toDecimalMark = num => num.toLocaleString('en-US'); ``` @@ -9594,20 +9616,20 @@ const toDecimalMark = num => num.toLocaleString('en-US'); ```js toDecimalMark(12305030388.9087); // "12,305,030,388.909" -``` +```
    [⬆ Back to top](#contents) -### toOrdinalSuffix - -Adds an ordinal suffix to a 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. - +### toOrdinalSuffix + +Adds an ordinal suffix to a 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), @@ -9626,20 +9648,20 @@ const toOrdinalSuffix = num => { ```js toOrdinalSuffix('123'); // "123rd" -``` +```
    [⬆ Back to top](#contents) -### validateNumber - -Returns `true` if the given value is a number, `false` otherwise. - -Use `!isNaN()` in combination with `parseFloat()` to check if the argument is a number. -Use `isFinite()` to check if the number is finite. -Use `Number()` to check if the coercion holds. - +### validateNumber + +Returns `true` if the given value is a number, `false` otherwise. + +Use `!isNaN()` in combination with `parseFloat()` to check if the argument is a number. +Use `isFinite()` to check if the number is finite. +Use `Number()` to check if the coercion holds. + ```js const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; ``` @@ -9649,19 +9671,19 @@ const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == ```js validateNumber('10'); // true -``` +```
    [⬆ Back to top](#contents) -### yesNo - -Returns `true` if the string is `y`/`yes` or `false` if the string is `n`/`no`. - -Use `RegExp.test()` to check if the string evaluates to `y/yes` or `n/no`. -Omit the second argument, `def` to set the default answer as `no`. - +### yesNo + +Returns `true` if the string is `y`/`yes` or `false` if the string is `n`/`no`. + +Use `RegExp.test()` to check if the string evaluates to `y/yes` or `n/no`. +Omit the second argument, `def` to set the default answer as `no`. + ```js const yesNo = (val, def = false) => /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; @@ -9675,22 +9697,22 @@ yesNo('Y'); // true yesNo('yes'); // true yesNo('No'); // false yesNo('Foo', true); // true -``` +```
    [⬆ Back to top](#contents) -## Collaborators - -| [](https://github.com/Chalarangelo)
    [Angelos Chalaris](https://github.com/Chalarangelo) | [](https://github.com/flxwu)
    [Felix Wu](https://github.com/Pl4gue) | [](https://github.com/fejes713)
    [Stefan Feješ](https://github.com/fejes713) | [](https://github.com/kingdavidmartins)
    [King David Martins](https://github.com/iamsoorena) | [](https://github.com/iamsoorena)
    [Soorena Soleimani](https://github.com/iamsoorena) | -| --- | --- | --- | --- | --- | -| [](https://github.com/elderhsouza)
    [Elder Henrique Souza](https://github.com/elderhsouza) | [](https://github.com/skatcat31)
    [Robert Mennell](https://github.com/skatcat31) | [](https://github.com/atomiks)
    [atomiks](https://github.com/atomiks) | - - -## Credits - -*Logos made by [Angelos Chalaris](https://github.com/Chalarangelo) are licensed under the [MIT](https://opensource.org/licenses/MIT) license.* -*This README is built using [markdown-builder](https://github.com/30-seconds/markdown-builder).* +## Collaborators + +| [](https://github.com/Chalarangelo)
    [Angelos Chalaris](https://github.com/Chalarangelo) | [](https://github.com/flxwu)
    [Felix Wu](https://github.com/Pl4gue) | [](https://github.com/fejes713)
    [Stefan Feješ](https://github.com/fejes713) | [](https://github.com/kingdavidmartins)
    [King David Martins](https://github.com/iamsoorena) | [](https://github.com/iamsoorena)
    [Soorena Soleimani](https://github.com/iamsoorena) | +| --- | --- | --- | --- | --- | +| [](https://github.com/elderhsouza)
    [Elder Henrique Souza](https://github.com/elderhsouza) | [](https://github.com/skatcat31)
    [Robert Mennell](https://github.com/skatcat31) | [](https://github.com/atomiks)
    [atomiks](https://github.com/atomiks) | + + +## Credits + +*Logos made by [Angelos Chalaris](https://github.com/Chalarangelo) are licensed under the [MIT](https://opensource.org/licenses/MIT) license.* +*This README is built using [markdown-builder](https://github.com/30-seconds/markdown-builder).* diff --git a/dist/_30s.es5.js b/dist/_30s.es5.js index 0607161b4..9a00320e4 100644 --- a/dist/_30s.es5.js +++ b/dist/_30s.es5.js @@ -118,54 +118,6 @@ var crypto = typeof require !== "undefined" && require('crypto'); - var CSVToArray = function CSVToArray(data) { - var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; - var omitFirstRow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - return data.slice(omitFirstRow ? data.indexOf('\n') + 1 : 0).split('\n').map(function (v) { - return v.split(delimiter); - }); - }; - var CSVToJSON = function CSVToJSON(data) { - var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; - var titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data.slice(data.indexOf('\n') + 1).split('\n').map(function (v) { - var values = v.split(delimiter); - return titles.reduce(function (obj, title, index) { - return obj[title] = values[index], obj; - }, {}); - }); - }; - var JSONToFile = function JSONToFile(obj, filename) { - return fs.writeFile("".concat(filename, ".json"), JSON.stringify(obj, null, 2)); - }; - var JSONtoCSV = function JSONtoCSV(arr, columns) { - var delimiter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ','; - return [columns.join(delimiter)].concat(_toConsumableArray(arr.map(function (obj) { - return columns.reduce(function (acc, key) { - return "".concat(acc).concat(!acc.length ? '' : delimiter, "\"").concat(!obj[key] ? '' : obj[key], "\""); - }, ''); - }))).join('\n'); - }; - var RGBToHex = function RGBToHex(r, g, b) { - return ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); - }; - var URLJoin = function URLJoin() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - return args.join('/').replace(/[\/]+/g, '/').replace(/^(.+):\//, '$1://').replace(/^file:/, 'file:/').replace(/\/(\?|&|#[^!])/g, '$1').replace(/\?/g, '&').replace('&', '?'); - }; - var UUIDGeneratorBrowser = function UUIDGeneratorBrowser() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { - return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16); - }); - }; - var UUIDGeneratorNode = function UUIDGeneratorNode() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { - return (c ^ crypto.randomBytes(1)[0] & 15 >> c / 4).toString(16); - }); - }; var all = function all(arr) { var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Boolean; return arr.every(fn); @@ -200,8 +152,8 @@ }; var ary = function ary(fn, n) { return function () { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; } return fn.apply(void 0, _toConsumableArray(args.slice(0, n))); @@ -212,8 +164,8 @@ }; var attempt = function attempt(fn) { try { - for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { - args[_key3 - 1] = arguments[_key3]; + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; } return fn.apply(void 0, args); @@ -222,8 +174,8 @@ } }; var average = function average() { - for (var _len4 = arguments.length, nums = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { - nums[_key4] = arguments[_key4]; + for (var _len3 = arguments.length, nums = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + nums[_key3] = arguments[_key3]; } return nums.reduce(function (acc, val) { @@ -248,21 +200,21 @@ }, [[], []]); }; var bind = function bind(fn, context) { - for (var _len5 = arguments.length, boundArgs = new Array(_len5 > 2 ? _len5 - 2 : 0), _key5 = 2; _key5 < _len5; _key5++) { - boundArgs[_key5 - 2] = arguments[_key5]; + for (var _len4 = arguments.length, boundArgs = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) { + boundArgs[_key4 - 2] = arguments[_key4]; } return function () { - for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { - args[_key6] = arguments[_key6]; + for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; } return fn.apply(context, boundArgs.concat(args)); }; }; var bindAll = function bindAll(obj) { - for (var _len7 = arguments.length, fns = new Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) { - fns[_key7 - 1] = arguments[_key7]; + for (var _len6 = arguments.length, fns = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { + fns[_key6 - 1] = arguments[_key6]; } return fns.forEach(function (fn) { @@ -272,13 +224,13 @@ }); }; var bindKey = function bindKey(context, fn) { - for (var _len8 = arguments.length, boundArgs = new Array(_len8 > 2 ? _len8 - 2 : 0), _key8 = 2; _key8 < _len8; _key8++) { - boundArgs[_key8 - 2] = arguments[_key8]; + for (var _len7 = arguments.length, boundArgs = new Array(_len7 > 2 ? _len7 - 2 : 0), _key7 = 2; _key7 < _len7; _key7++) { + boundArgs[_key7 - 2] = arguments[_key7]; } return function () { - for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { - args[_key9] = arguments[_key9]; + for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { + args[_key8] = arguments[_key8]; } return context[fn].apply(context, boundArgs.concat(args)); @@ -308,8 +260,8 @@ return new Blob([str]).size; }; var call = function call(key) { - for (var _len10 = arguments.length, args = new Array(_len10 > 1 ? _len10 - 1 : 0), _key10 = 1; _key10 < _len10; _key10++) { - args[_key10 - 1] = arguments[_key10]; + for (var _len9 = arguments.length, args = new Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) { + args[_key9 - 1] = arguments[_key9]; } return function (context) { @@ -357,8 +309,8 @@ return new RegExp(regExp.source, regExp.flags); }; var coalesce = function coalesce() { - for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { - args[_key11] = arguments[_key11]; + for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) { + args[_key10] = arguments[_key10]; } return args.find(function (_) { @@ -367,8 +319,8 @@ }; var coalesceFactory = function coalesceFactory(valid) { return function () { - for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { - args[_key12] = arguments[_key12]; + for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { + args[_key11] = arguments[_key11]; } return args.find(valid); @@ -376,16 +328,16 @@ }; var collectInto = function collectInto(fn) { return function () { - for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { - args[_key13] = arguments[_key13]; + for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { + args[_key12] = arguments[_key12]; } return fn(args); }; }; var colorize = function colorize() { - for (var _len14 = arguments.length, args = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { - args[_key14] = arguments[_key14]; + for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { + args[_key13] = arguments[_key13]; } return { @@ -414,8 +366,8 @@ return str.replace(/\s{2,}/g, ' '); }; var compose = function compose() { - for (var _len15 = arguments.length, fns = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) { - fns[_key15] = arguments[_key15]; + for (var _len14 = arguments.length, fns = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { + fns[_key14] = arguments[_key14]; } return fns.reduce(function (f, g) { @@ -425,8 +377,8 @@ }); }; var composeRight = function composeRight() { - for (var _len16 = arguments.length, fns = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) { - fns[_key16] = arguments[_key16]; + for (var _len15 = arguments.length, fns = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) { + fns[_key15] = arguments[_key15]; } return fns.reduce(function (f, g) { @@ -437,8 +389,8 @@ }; var converge = function converge(converger, fns) { return function () { - for (var _len17 = arguments.length, args = new Array(_len17), _key17 = 0; _key17 < _len17; _key17++) { - args[_key17] = arguments[_key17]; + for (var _len16 = arguments.length, args = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) { + args[_key16] = arguments[_key16]; } return converger.apply(void 0, _toConsumableArray(fns.map(function (fn) { @@ -471,11 +423,6 @@ return acc; }, {}); }; - var countOccurrences = function countOccurrences(arr, val) { - return arr.reduce(function (a, v) { - return v === val ? a + 1 : a; - }, 0); - }; var counter = function counter(selector, start, end) { var step = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; var duration = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 2000; @@ -491,6 +438,11 @@ return timer; }; + var countOccurrences = function countOccurrences(arr, val) { + return arr.reduce(function (a, v) { + return v === val ? a + 1 : a; + }, 0); + }; var createDirIfNotExists = function createDirIfNotExists(dir) { return !fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined; }; @@ -519,14 +471,31 @@ } }; }; + var CSVToArray = function CSVToArray(data) { + var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; + var omitFirstRow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return data.slice(omitFirstRow ? data.indexOf('\n') + 1 : 0).split('\n').map(function (v) { + return v.split(delimiter); + }); + }; + var CSVToJSON = function CSVToJSON(data) { + var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; + var titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data.slice(data.indexOf('\n') + 1).split('\n').map(function (v) { + var values = v.split(delimiter); + return titles.reduce(function (obj, title, index) { + return obj[title] = values[index], obj; + }, {}); + }); + }; var currentURL = function currentURL() { return window.location.href; }; var curry = function curry(fn) { var arity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : fn.length; - for (var _len18 = arguments.length, args = new Array(_len18 > 2 ? _len18 - 2 : 0), _key18 = 2; _key18 < _len18; _key18++) { - args[_key18 - 2] = arguments[_key18]; + for (var _len17 = arguments.length, args = new Array(_len17 > 2 ? _len17 - 2 : 0), _key17 = 2; _key17 < _len17; _key17++) { + args[_key17 - 2] = arguments[_key17]; } return arity <= args.length ? fn.apply(void 0, args) : curry.bind.apply(curry, [null, fn, arity].concat(args)); @@ -540,8 +509,8 @@ return function () { var _this = this; - for (var _len19 = arguments.length, args = new Array(_len19), _key19 = 0; _key19 < _len19; _key19++) { - args[_key19] = arguments[_key19]; + for (var _len18 = arguments.length, args = new Array(_len18), _key18 = 0; _key18 < _len18; _key18++) { + args[_key18] = arguments[_key18]; } clearTimeout(timeoutId); @@ -587,15 +556,15 @@ }, {}) : obj; }; var defaults = function defaults(obj) { - for (var _len20 = arguments.length, defs = new Array(_len20 > 1 ? _len20 - 1 : 0), _key20 = 1; _key20 < _len20; _key20++) { - defs[_key20 - 1] = arguments[_key20]; + for (var _len19 = arguments.length, defs = new Array(_len19 > 1 ? _len19 - 1 : 0), _key19 = 1; _key19 < _len19; _key19++) { + defs[_key19 - 1] = arguments[_key19]; } return Object.assign.apply(Object, [{}, obj].concat(_toConsumableArray(defs.reverse()), [obj])); }; var defer = function defer(fn) { - for (var _len21 = arguments.length, args = new Array(_len21 > 1 ? _len21 - 1 : 0), _key21 = 1; _key21 < _len21; _key21++) { - args[_key21 - 1] = arguments[_key21]; + for (var _len20 = arguments.length, args = new Array(_len20 > 1 ? _len20 - 1 : 0), _key20 = 1; _key20 < _len20; _key20++) { + args[_key20 - 1] = arguments[_key20]; } return setTimeout.apply(void 0, [fn, 1].concat(args)); @@ -604,8 +573,8 @@ return deg * Math.PI / 180.0; }; var delay = function delay(fn, wait) { - for (var _len22 = arguments.length, args = new Array(_len22 > 2 ? _len22 - 2 : 0), _key22 = 2; _key22 < _len22; _key22++) { - args[_key22 - 2] = arguments[_key22]; + for (var _len21 = arguments.length, args = new Array(_len21 > 2 ? _len21 - 2 : 0), _key21 = 2; _key21 < _len21; _key21++) { + args[_key21 - 2] = arguments[_key21]; } return setTimeout.apply(void 0, [fn, wait].concat(args)); @@ -826,8 +795,8 @@ }; var flip = function flip(fn) { return function (first) { - for (var _len23 = arguments.length, rest = new Array(_len23 > 1 ? _len23 - 1 : 0), _key23 = 1; _key23 < _len23; _key23++) { - rest[_key23 - 1] = arguments[_key23]; + for (var _len22 = arguments.length, rest = new Array(_len22 > 1 ? _len22 - 1 : 0), _key22 = 1; _key22 < _len22; _key22++) { + rest[_key22 - 1] = arguments[_key22]; } return fn.apply(void 0, rest.concat([first])); @@ -836,16 +805,6 @@ var forEachRight = function forEachRight(arr, callback) { return arr.slice(0).reverse().forEach(callback); }; - var forOwn = function forOwn(obj, fn) { - return Object.keys(obj).forEach(function (key) { - return fn(obj[key], key, obj); - }); - }; - var forOwnRight = function forOwnRight(obj, fn) { - return Object.keys(obj).reverse().forEach(function (key) { - return fn(obj[key], key, obj); - }); - }; var formatDuration = function formatDuration(ms) { if (ms < 0) ms = -ms; var time = { @@ -865,6 +824,16 @@ return "".concat(val, " ").concat(key).concat(val !== 1 ? 's' : ''); }).join(', '); }; + var forOwn = function forOwn(obj, fn) { + return Object.keys(obj).forEach(function (key) { + return fn(obj[key], key, obj); + }); + }; + var forOwnRight = function forOwnRight(obj, fn) { + return Object.keys(obj).reverse().forEach(function (key) { + return fn(obj[key], key, obj); + }); + }; var fromCamelCase = function fromCamelCase(str) { var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '_'; return str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase(); @@ -883,8 +852,8 @@ return !y ? x : gcd(y, x % y); }; - for (var _len24 = arguments.length, arr = new Array(_len24), _key24 = 0; _key24 < _len24; _key24++) { - arr[_key24] = arguments[_key24]; + for (var _len23 = arguments.length, arr = new Array(_len23), _key23 = 0; _key23 < _len23; _key23++) { + arr[_key23] = arguments[_key23]; } return arr.concat().reduce(function (a, b) { @@ -901,8 +870,8 @@ }); }; var get = function get(from) { - for (var _len25 = arguments.length, selectors = new Array(_len25 > 1 ? _len25 - 1 : 0), _key25 = 1; _key25 < _len25; _key25++) { - selectors[_key25 - 1] = arguments[_key25]; + for (var _len24 = arguments.length, selectors = new Array(_len24 > 1 ? _len24 - 1 : 0), _key24 = 1; _key24 < _len24; _key24++) { + selectors[_key24 - 1] = arguments[_key24]; } return selectors.concat().map(function (s) { @@ -964,8 +933,8 @@ return el.classList.contains(className); }; var hasFlags = function hasFlags() { - for (var _len26 = arguments.length, flags = new Array(_len26), _key26 = 0; _key26 < _len26; _key26++) { - flags[_key26] = arguments[_key26]; + for (var _len25 = arguments.length, flags = new Array(_len25), _key25 = 0; _key25 < _len25; _key25++) { + flags[_key25] = arguments[_key25]; } return flags.every(function (flag) { @@ -1004,8 +973,8 @@ return 'rgb' + (alpha ? 'a' : '') + '(' + (h >>> (alpha ? 24 : 16)) + ', ' + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ', ' + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + (alpha ? ", ".concat(h & 0x000000ff) : '') + ')'; }; var hide = function hide() { - for (var _len27 = arguments.length, el = new Array(_len27), _key27 = 0; _key27 < _len27; _key27++) { - el[_key27] = arguments[_key27]; + for (var _len26 = arguments.length, el = new Array(_len26), _key26 = 0; _key26 < _len26; _key26++) { + el[_key26] = arguments[_key26]; } return el.concat().forEach(function (e) { @@ -1056,17 +1025,6 @@ return 1000 * iterations / (performance.now() - before); }; - var inRange = function inRange(n, start) { - var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - - if (end && start > end) { - var _ref12 = [start, end]; - end = _ref12[0]; - start = _ref12[1]; - } - - return end == null ? n >= 0 && n < start : n >= start && n < end; - }; var indentString = function indentString(str, count) { var indent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ' '; return str.replace(/^/gm, indent.repeat(count)); @@ -1112,8 +1070,8 @@ return Array(n).fill(val); }; var initializeNDArray = function initializeNDArray(val) { - for (var _len28 = arguments.length, args = new Array(_len28 > 1 ? _len28 - 1 : 0), _key28 = 1; _key28 < _len28; _key28++) { - args[_key28 - 1] = arguments[_key28]; + for (var _len27 = arguments.length, args = new Array(_len27 > 1 ? _len27 - 1 : 0), _key27 = 1; _key27 < _len27; _key27++) { + args[_key27 - 1] = arguments[_key27]; } return args.length === 0 ? val : Array.from({ @@ -1122,6 +1080,17 @@ return initializeNDArray.apply(void 0, [val].concat(_toConsumableArray(args.slice(1)))); }); }; + var inRange = function inRange(n, start) { + var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + if (end && start > end) { + var _ref12 = [start, end]; + end = _ref12[0]; + start = _ref12[1]; + } + + return end == null ? n >= 0 && n < start : n >= start && n < end; + }; var insertAfter = function insertAfter(el, htmlString) { return el.insertAdjacentHTML('afterend', htmlString); }; @@ -1312,6 +1281,17 @@ return i === arr.length - 2 ? acc + val + end : i === arr.length - 1 ? acc + val : acc + val + separator; }, ''); }; + var JSONtoCSV = function JSONtoCSV(arr, columns) { + var delimiter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ','; + return [columns.join(delimiter)].concat(_toConsumableArray(arr.map(function (obj) { + return columns.reduce(function (acc, key) { + return "".concat(acc).concat(!acc.length ? '' : delimiter, "\"").concat(!obj[key] ? '' : obj[key], "\""); + }, ''); + }))).join('\n'); + }; + var JSONToFile = function JSONToFile(obj, filename) { + return fs.writeFile("".concat(filename, ".json"), JSON.stringify(obj, null, 2)); + }; var last = function last(arr) { return arr[arr.length - 1]; }; @@ -1324,8 +1304,8 @@ return x * y / gcd(x, y); }; - for (var _len29 = arguments.length, arr = new Array(_len29), _key29 = 0; _key29 < _len29; _key29++) { - arr[_key29] = arguments[_key29]; + for (var _len28 = arguments.length, arr = new Array(_len28), _key28 = 0; _key28 < _len28; _key28++) { + arr[_key28] = arguments[_key28]; } return arr.concat().reduce(function (a, b) { @@ -1333,8 +1313,8 @@ }); }; var longestItem = function longestItem() { - for (var _len30 = arguments.length, vals = new Array(_len30), _key30 = 0; _key30 < _len30; _key30++) { - vals[_key30] = arguments[_key30]; + for (var _len29 = arguments.length, vals = new Array(_len29), _key29 = 0; _key29 < _len29; _key29++) { + vals[_key29] = arguments[_key29]; } return vals.reduce(function (a, x) { @@ -1364,6 +1344,9 @@ return acc; }, {}); }; + var mapNumRange = function mapNumRange(num, inMin, inMax, outMin, outMax) { + return (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; + }; var mapObject = function mapObject(arr, fn) { return function (a) { return a = [arr, arr.map(fn)], a[0].reduce(function (acc, val, ind) { @@ -1405,8 +1388,8 @@ var maxDate = function maxDate() { var _Math$max; - for (var _len31 = arguments.length, dates = new Array(_len31), _key31 = 0; _key31 < _len31; _key31++) { - dates[_key31] = arguments[_key31]; + for (var _len30 = arguments.length, dates = new Array(_len30), _key30 = 0; _key30 < _len30; _key30++) { + dates[_key30] = arguments[_key30]; } return new Date((_Math$max = Math.max).apply.apply(_Math$max, [null].concat(dates))); @@ -1436,8 +1419,8 @@ return cached; }; var merge = function merge() { - for (var _len32 = arguments.length, objs = new Array(_len32), _key32 = 0; _key32 < _len32; _key32++) { - objs[_key32] = arguments[_key32]; + for (var _len31 = arguments.length, objs = new Array(_len31), _key31 = 0; _key31 < _len31; _key31++) { + objs[_key31] = arguments[_key31]; } return objs.concat().reduce(function (acc, obj) { @@ -1466,8 +1449,8 @@ var minDate = function minDate() { var _Math$min; - for (var _len33 = arguments.length, dates = new Array(_len33), _key33 = 0; _key33 < _len33; _key33++) { - dates[_key33] = arguments[_key33]; + for (var _len32 = arguments.length, dates = new Array(_len32), _key32 = 0; _key32 < _len32; _key32++) { + dates[_key32] = arguments[_key32]; } return new Date((_Math$min = Math.min).apply.apply(_Math$min, [null].concat(dates))); @@ -1516,8 +1499,8 @@ }; var nthArg = function nthArg(n) { return function () { - for (var _len34 = arguments.length, args = new Array(_len34), _key34 = 0; _key34 < _len34; _key34++) { - args[_key34] = arguments[_key34]; + for (var _len33 = arguments.length, args = new Array(_len33), _key33 = 0; _key33 < _len33; _key33++) { + args[_key33] = arguments[_key33]; } return args.slice(n)[0]; @@ -1588,6 +1571,19 @@ el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); if (opts.target) return delegatorFn; }; + var once = function once(fn) { + var called = false; + return function () { + if (called) return; + called = true; + + for (var _len34 = arguments.length, args = new Array(_len34), _key34 = 0; _key34 < _len34; _key34++) { + args[_key34] = arguments[_key34]; + } + + return fn.apply(this, args); + }; + }; var onUserInputChange = function onUserInputChange(callback) { var type = 'mouse', lastTime = 0; @@ -1603,19 +1599,6 @@ type = 'touch', callback(type), document.addEventListener('mousemove', mousemoveHandler); }); }; - var once = function once(fn) { - var called = false; - return function () { - if (called) return; - called = true; - - for (var _len35 = arguments.length, args = new Array(_len35), _key35 = 0; _key35 < _len35; _key35++) { - args[_key35] = arguments[_key35]; - } - - return fn.apply(this, args); - }; - }; var orderBy = function orderBy(arr, props, orders) { return _toConsumableArray(arr).sort(function (a, b) { return props.reduce(function (acc, prop, i) { @@ -1633,13 +1616,13 @@ }); }; var over = function over() { - for (var _len36 = arguments.length, fns = new Array(_len36), _key36 = 0; _key36 < _len36; _key36++) { - fns[_key36] = arguments[_key36]; + for (var _len35 = arguments.length, fns = new Array(_len35), _key35 = 0; _key35 < _len35; _key35++) { + fns[_key35] = arguments[_key35]; } return function () { - for (var _len37 = arguments.length, args = new Array(_len37), _key37 = 0; _key37 < _len37; _key37++) { - args[_key37] = arguments[_key37]; + for (var _len36 = arguments.length, args = new Array(_len36), _key36 = 0; _key36 < _len36; _key36++) { + args[_key36] = arguments[_key36]; } return fns.map(function (fn) { @@ -1649,8 +1632,8 @@ }; var overArgs = function overArgs(fn, transforms) { return function () { - for (var _len38 = arguments.length, args = new Array(_len38), _key38 = 0; _key38 < _len38; _key38++) { - args[_key38] = arguments[_key38]; + for (var _len37 = arguments.length, args = new Array(_len37), _key37 = 0; _key37 < _len37; _key37++) { + args[_key37] = arguments[_key37]; } return fn.apply(void 0, _toConsumableArray(args.map(function (val, i) { @@ -1675,26 +1658,26 @@ }, {}); }; var partial = function partial(fn) { - for (var _len39 = arguments.length, partials = new Array(_len39 > 1 ? _len39 - 1 : 0), _key39 = 1; _key39 < _len39; _key39++) { - partials[_key39 - 1] = arguments[_key39]; + for (var _len38 = arguments.length, partials = new Array(_len38 > 1 ? _len38 - 1 : 0), _key38 = 1; _key38 < _len38; _key38++) { + partials[_key38 - 1] = arguments[_key38]; } return function () { - for (var _len40 = arguments.length, args = new Array(_len40), _key40 = 0; _key40 < _len40; _key40++) { - args[_key40] = arguments[_key40]; + for (var _len39 = arguments.length, args = new Array(_len39), _key39 = 0; _key39 < _len39; _key39++) { + args[_key39] = arguments[_key39]; } return fn.apply(void 0, partials.concat(args)); }; }; var partialRight = function partialRight(fn) { - for (var _len41 = arguments.length, partials = new Array(_len41 > 1 ? _len41 - 1 : 0), _key41 = 1; _key41 < _len41; _key41++) { - partials[_key41 - 1] = arguments[_key41]; + for (var _len40 = arguments.length, partials = new Array(_len40 > 1 ? _len40 - 1 : 0), _key40 = 1; _key40 < _len40; _key40++) { + partials[_key40 - 1] = arguments[_key40]; } return function () { - for (var _len42 = arguments.length, args = new Array(_len42), _key42 = 0; _key42 < _len42; _key42++) { - args[_key42] = arguments[_key42]; + for (var _len41 = arguments.length, args = new Array(_len41), _key41 = 0; _key41 < _len41; _key41++) { + args[_key41] = arguments[_key41]; } return fn.apply(void 0, args.concat(partials)); @@ -1732,8 +1715,8 @@ }, {}); }; var pipeAsyncFunctions = function pipeAsyncFunctions() { - for (var _len43 = arguments.length, fns = new Array(_len43), _key43 = 0; _key43 < _len43; _key43++) { - fns[_key43] = arguments[_key43]; + for (var _len42 = arguments.length, fns = new Array(_len42), _key42 = 0; _key42 < _len42; _key42++) { + fns[_key42] = arguments[_key42]; } return function (arg) { @@ -1743,8 +1726,8 @@ }; }; var pipeFunctions = function pipeFunctions() { - for (var _len44 = arguments.length, fns = new Array(_len44), _key44 = 0; _key44 < _len44; _key44++) { - fns[_key44] = arguments[_key44]; + for (var _len43 = arguments.length, fns = new Array(_len43), _key43 = 0; _key43 < _len43; _key43++) { + fns[_key43] = arguments[_key43]; } return fns.reduce(function (f, g) { @@ -1811,8 +1794,8 @@ }; var promisify = function promisify(func) { return function () { - for (var _len45 = arguments.length, args = new Array(_len45), _key45 = 0; _key45 < _len45; _key45++) { - args[_key45] = arguments[_key45]; + for (var _len44 = arguments.length, args = new Array(_len44), _key44 = 0; _key44 < _len44; _key44++) { + args[_key44] = arguments[_key44]; } return new Promise(function (resolve, reject) { @@ -1823,8 +1806,8 @@ }; }; var pull = function pull(arr) { - for (var _len46 = arguments.length, args = new Array(_len46 > 1 ? _len46 - 1 : 0), _key46 = 1; _key46 < _len46; _key46++) { - args[_key46 - 1] = arguments[_key46]; + for (var _len45 = arguments.length, args = new Array(_len45 > 1 ? _len45 - 1 : 0), _key45 = 1; _key45 < _len45; _key45++) { + args[_key45 - 1] = arguments[_key45]; } var argState = Array.isArray(args[0]) ? args[0] : args; @@ -1864,8 +1847,8 @@ return removed; }; var pullBy = function pullBy(arr) { - for (var _len47 = arguments.length, args = new Array(_len47 > 1 ? _len47 - 1 : 0), _key47 = 1; _key47 < _len47; _key47++) { - args[_key47 - 1] = arguments[_key47]; + for (var _len46 = arguments.length, args = new Array(_len46 > 1 ? _len46 - 1 : 0), _key46 = 1; _key46 < _len46; _key46++) { + args[_key46 - 1] = arguments[_key46]; } var length = args.length; @@ -1908,8 +1891,8 @@ }; var rearg = function rearg(fn, indexes) { return function () { - for (var _len48 = arguments.length, args = new Array(_len48), _key48 = 0; _key48 < _len48; _key48++) { - args[_key48] = arguments[_key48]; + for (var _len47 = arguments.length, args = new Array(_len47), _key47 = 0; _key47 < _len47; _key47++) { + args[_key47] = arguments[_key47]; } return fn.apply(void 0, _toConsumableArray(indexes.map(function (i) { @@ -1949,6 +1932,14 @@ var asLink = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; return asLink ? window.location.href = url : window.location.replace(url); }; + var reducedFilter = function reducedFilter(data, keys, fn) { + return data.filter(fn).map(function (el) { + return keys.reduce(function (acc, key) { + acc[key] = el[key]; + return acc; + }, {}); + }); + }; var reduceSuccessive = function reduceSuccessive(arr, fn, acc) { return arr.reduce(function (res, val, i, arr) { return res.push(fn(res.slice(-1)[0], val, i, arr)), res; @@ -1962,14 +1953,6 @@ return comparator(a, b) >= 0 ? b : a; }); }; - var reducedFilter = function reducedFilter(data, keys, fn) { - return data.filter(fn).map(function (el) { - return keys.reduce(function (acc, key) { - acc[key] = el[key]; - return acc; - }, {}); - }); - }; var reject = function reject(pred, array) { return array.filter(function () { return !pred.apply(void 0, arguments); @@ -1992,6 +1975,9 @@ var reverseString = function reverseString(str) { return _toConsumableArray(str).reverse().join(''); }; + var RGBToHex = function RGBToHex(r, g, b) { + return ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); + }; var round = function round(n) { var decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return Number("".concat(Math.round("".concat(n, "e").concat(decimals)), "e-").concat(decimals)); @@ -2062,15 +2048,15 @@ var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var delCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - for (var _len49 = arguments.length, elements = new Array(_len49 > 3 ? _len49 - 3 : 0), _key49 = 3; _key49 < _len49; _key49++) { - elements[_key49 - 3] = arguments[_key49]; + for (var _len48 = arguments.length, elements = new Array(_len48 > 3 ? _len48 - 3 : 0), _key48 = 3; _key48 < _len48; _key48++) { + elements[_key48 - 3] = arguments[_key48]; } return arr.slice(0, index).concat(elements).concat(arr.slice(index + delCount)); }; var show = function show() { - for (var _len50 = arguments.length, el = new Array(_len50), _key50 = 0; _key50 < _len50; _key50++) { - el[_key50] = arguments[_key50]; + for (var _len49 = arguments.length, el = new Array(_len49), _key49 = 0; _key49 < _len49; _key49++) { + el[_key49] = arguments[_key49]; } return el.concat().forEach(function (e) { @@ -2189,8 +2175,8 @@ return str.replace(/<[^>]*>/g, ''); }; var sum = function sum() { - for (var _len51 = arguments.length, arr = new Array(_len51), _key51 = 0; _key51 < _len51; _key51++) { - arr[_key51] = arguments[_key51]; + for (var _len50 = arguments.length, arr = new Array(_len50), _key50 = 0; _key50 < _len50; _key50++) { + arr[_key50] = arguments[_key50]; } return arr.concat().reduce(function (acc, val) { @@ -2313,18 +2299,18 @@ } }; }; - var timeTaken = function timeTaken(callback) { - console.time('timeTaken'); - var r = callback(); - console.timeEnd('timeTaken'); - return r; - }; var times = function times(n, fn) { var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var i = 0; while (fn.call(context, i) !== false && ++i < n) {} }; + var timeTaken = function timeTaken(callback) { + console.time('timeTaken'); + var r = callback(); + console.timeEnd('timeTaken'); + return r; + }; var toCamelCase = function toCamelCase(str) { var s = str && str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map(function (x) { return x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase(); @@ -2341,6 +2327,9 @@ var toDecimalMark = function toDecimalMark(num) { return num.toLocaleString('en-US'); }; + var toggleClass = function toggleClass(el, className) { + return el.classList.toggle(className); + }; var toHash = function toHash(object, key) { return Array.prototype.reduce.call(object, function (acc, data, index) { return acc[!key ? index : data[key]] = data, acc; @@ -2351,6 +2340,11 @@ return x.toLowerCase(); }).join('-'); }; + var tomorrow = function tomorrow() { + var t = new Date(); + t.setDate(t.getDate() + 1); + return t.toISOString().split('T')[0]; + }; var toOrdinalSuffix = function toOrdinalSuffix(num) { var int = parseInt(num), digits = [int % 10, int % 100], @@ -2372,14 +2366,6 @@ return x.charAt(0).toUpperCase() + x.slice(1); }).join(' '); }; - var toggleClass = function toggleClass(el, className) { - return el.classList.toggle(className); - }; - var tomorrow = function tomorrow() { - var t = new Date(); - t.setDate(t.getDate() + 1); - return t.toISOString().split('T')[0]; - }; var transform = function transform(obj, fn, acc) { return Object.keys(obj).reduce(function (a, k) { return fn(a, obj[k], k, obj); @@ -2414,8 +2400,8 @@ }; }; - for (var _len52 = arguments.length, args = new Array(_len52), _key52 = 0; _key52 < _len52; _key52++) { - args[_key52] = arguments[_key52]; + for (var _len51 = arguments.length, args = new Array(_len51), _key51 = 0; _key51 < _len51; _key51++) { + args[_key51] = arguments[_key51]; } if (n > args.length) throw new RangeError('Arguments too few!'); @@ -2528,6 +2514,23 @@ return fn.apply(void 0, _toConsumableArray(val)); }); }; + var URLJoin = function URLJoin() { + for (var _len52 = arguments.length, args = new Array(_len52), _key52 = 0; _key52 < _len52; _key52++) { + args[_key52] = arguments[_key52]; + } + + return args.join('/').replace(/[\/]+/g, '/').replace(/^(.+):\//, '$1://').replace(/^file:/, 'file:/').replace(/\/(\?|&|#[^!])/g, '$1').replace(/\?/g, '&').replace('&', '?'); + }; + var UUIDGeneratorBrowser = function UUIDGeneratorBrowser() { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { + return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16); + }); + }; + var UUIDGeneratorNode = function UUIDGeneratorNode() { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { + return (c ^ crypto.randomBytes(1)[0] & 15 >> c / 4).toString(16); + }); + }; var validateNumber = function validateNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; }; @@ -2602,14 +2605,6 @@ }); }; - exports.CSVToArray = CSVToArray; - exports.CSVToJSON = CSVToJSON; - exports.JSONToFile = JSONToFile; - exports.JSONtoCSV = JSONtoCSV; - exports.RGBToHex = RGBToHex; - exports.URLJoin = URLJoin; - exports.UUIDGeneratorBrowser = UUIDGeneratorBrowser; - exports.UUIDGeneratorNode = UUIDGeneratorNode; exports.all = all; exports.allEqual = allEqual; exports.any = any; @@ -2649,11 +2644,13 @@ exports.converge = converge; exports.copyToClipboard = copyToClipboard; exports.countBy = countBy; - exports.countOccurrences = countOccurrences; exports.counter = counter; + exports.countOccurrences = countOccurrences; exports.createDirIfNotExists = createDirIfNotExists; exports.createElement = createElement; exports.createEventHub = createEventHub; + exports.CSVToArray = CSVToArray; + exports.CSVToJSON = CSVToJSON; exports.currentURL = currentURL; exports.curry = curry; exports.dayOfYear = dayOfYear; @@ -2699,9 +2696,9 @@ exports.flattenObject = flattenObject; exports.flip = flip; exports.forEachRight = forEachRight; + exports.formatDuration = formatDuration; exports.forOwn = forOwn; exports.forOwnRight = forOwnRight; - exports.formatDuration = formatDuration; exports.fromCamelCase = fromCamelCase; exports.functionName = functionName; exports.functions = functions; @@ -2729,7 +2726,6 @@ exports.httpPost = httpPost; exports.httpsRedirect = httpsRedirect; exports.hz = hz; - exports.inRange = inRange; exports.indentString = indentString; exports.indexOfAll = indexOfAll; exports.initial = initial; @@ -2738,6 +2734,7 @@ exports.initializeArrayWithRangeRight = initializeArrayWithRangeRight; exports.initializeArrayWithValues = initializeArrayWithValues; exports.initializeNDArray = initializeNDArray; + exports.inRange = inRange; exports.insertAfter = insertAfter; exports.insertBefore = insertBefore; exports.intersection = intersection; @@ -2781,12 +2778,15 @@ exports.isValidJSON = isValidJSON; exports.isWritableStream = isWritableStream; exports.join = join; + exports.JSONtoCSV = JSONtoCSV; + exports.JSONToFile = JSONToFile; exports.last = last; exports.lcm = lcm; exports.longestItem = longestItem; exports.lowercaseKeys = lowercaseKeys; exports.luhnCheck = luhnCheck; exports.mapKeys = mapKeys; + exports.mapNumRange = mapNumRange; exports.mapObject = mapObject; exports.mapString = mapString; exports.mapValues = mapValues; @@ -2818,8 +2818,8 @@ exports.omit = omit; exports.omitBy = omitBy; exports.on = on; - exports.onUserInputChange = onUserInputChange; exports.once = once; + exports.onUserInputChange = onUserInputChange; exports.orderBy = orderBy; exports.over = over; exports.overArgs = overArgs; @@ -2854,14 +2854,15 @@ exports.rearg = rearg; exports.recordAnimationFrames = recordAnimationFrames; exports.redirect = redirect; + exports.reducedFilter = reducedFilter; exports.reduceSuccessive = reduceSuccessive; exports.reduceWhich = reduceWhich; - exports.reducedFilter = reducedFilter; exports.reject = reject; exports.remove = remove; exports.removeNonASCII = removeNonASCII; exports.renameKeys = renameKeys; exports.reverseString = reverseString; + exports.RGBToHex = RGBToHex; exports.round = round; exports.runAsync = runAsync; exports.runPromisesInSeries = runPromisesInSeries; @@ -2902,19 +2903,19 @@ exports.takeRightWhile = takeRightWhile; exports.takeWhile = takeWhile; exports.throttle = throttle; - exports.timeTaken = timeTaken; exports.times = times; + exports.timeTaken = timeTaken; exports.toCamelCase = toCamelCase; exports.toCurrency = toCurrency; exports.toDecimalMark = toDecimalMark; + exports.toggleClass = toggleClass; exports.toHash = toHash; exports.toKebabCase = toKebabCase; + exports.tomorrow = tomorrow; exports.toOrdinalSuffix = toOrdinalSuffix; exports.toSafeInteger = toSafeInteger; exports.toSnakeCase = toSnakeCase; exports.toTitleCase = toTitleCase; - exports.toggleClass = toggleClass; - exports.tomorrow = tomorrow; exports.transform = transform; exports.triggerEvent = triggerEvent; exports.truncateString = truncateString; @@ -2934,6 +2935,9 @@ exports.untildify = untildify; exports.unzip = unzip; exports.unzipWith = unzipWith; + exports.URLJoin = URLJoin; + exports.UUIDGeneratorBrowser = UUIDGeneratorBrowser; + exports.UUIDGeneratorNode = UUIDGeneratorNode; exports.validateNumber = validateNumber; exports.when = when; exports.without = without; diff --git a/dist/_30s.es5.min.js b/dist/_30s.es5.min.js index 915c85bd9..54e46db88 100644 --- a/dist/_30s.es5.min.js +++ b/dist/_30s.es5.min.js @@ -1 +1 @@ -(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?t(exports):'function'==typeof define&&define.amd?define(['exports'],t):t(e._30s={})})(this,function(e){'use strict';function t(e){return t='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&'function'==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?'symbol':typeof e},t(e)}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){for(var t=1;t>e/4).toString(16)})},e.UUIDGeneratorNode=function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(e){return(e^x.randomBytes(1)[0]&15>>e/4).toString(16)})},e.all=function(e){var t=1'.concat(e,'
  • ')}).join('')}()},e.ary=function(e,t){return function(){for(var n=arguments.length,i=Array(n),r=0;rt||t>e)return 0;if(0===t||t===e)return 1;if(1===t||t===e-1)return e;e-t=(document.documentElement.scrollHeight||document.documentElement.clientHeight)},e.btoa=function(e){return Buffer.from(e,'binary').toString('base64')},e.byteSize=function(e){return new Blob([e]).size},e.call=function(e){for(var t=arguments.length,n=Array(1(n-t)*i?-i:i,o=setInterval(function(){a+=l,document.querySelector(e).innerHTML=a,a>=n&&(document.querySelector(e).innerHTML=n),a>=n&&clearInterval(o)},j(k(r/(n-t))));return o},e.createDirIfNotExists=function(e){return S.existsSync(e)?void 0:S.mkdirSync(e)},e.createElement=function(e){var t=document.createElement('div');return t.innerHTML=e,t.firstElementChild},e.createEventHub=function(){return{hub:Object.create(null),emit:function(e,t){(this.hub[e]||[]).forEach(function(e){return e(t)})},on:function(e,t){this.hub[e]||(this.hub[e]=[]),this.hub[e].push(t)},off:function(e,t){var n=(this.hub[e]||[]).findIndex(function(e){return e===t});-1'"]/g,function(e){return{"&":'&',"<":'<',">":'>',"'":''','"':'"'}[e]||e})},e.escapeRegExp=function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')},e.everyNth=function(e,t){return e.filter(function(n,e){return e%t==t-1})},e.extendHex=function(e){return'#'+e.slice(e.startsWith('#')?1:0).split('').map(function(e){return e+e}).join('')},e.factorial=function e(t){return 0>t?function(){throw new TypeError('Negative numbers are not allowed!')}():1>=t?1:t*e(t-1)},e.fibonacci=function(e){return Array.from({length:e}).reduce(function(e,t,n){return e.concat(1e&&(e=-e);var t={day:k(e/864e5),hour:k(e/36e5)%24,minute:k(e/6e4)%60,second:k(e/1e3)%60,millisecond:k(e)%1e3};return Object.entries(t).filter(function(e){return 0!==e[1]}).map(function(e){var t=r(e,2),n=t[0],i=t[1];return''.concat(i,' ').concat(n).concat(1===i?'':'s')}).join(', ')},e.fromCamelCase=function(e){var t=1e?e%12+'am':e%12+'pm'},e.getScrollPosition=function(){var e=0>>(t?24:16))+', '+((n&(t?16711680:65280))>>>(t?16:8))+', '+((n&(t?65280:255))>>>(t?8:0))+(t?', '.concat(255&n):'')+')'},e.hide=function(){for(var e=arguments.length,t=Array(e),n=0;nn){var i=[t,n];n=i[0],t=i[1]}return null==n?0<=e&&e=t&&et},e.isAnagram=function(e,t){var n=function(e){return e.toLowerCase().replace(/[^a-z0-9]/gi,'').split('').sort().join('')};return n(e)===n(t)},e.isArrayLike=function(e){return null!=e&&'function'==typeof e[Symbol.iterator]},e.isBeforeDate=function(e,t){return ee.length?t:e})},e.lowercaseKeys=function(e){return Object.keys(e).reduce(function(t,n){return t[n.toLowerCase()]=e[n],t},{})},e.luhnCheck=function(e){var t=(e+'').split('').reverse().map(function(e){return parseInt(e)}),n=t.splice(0,1)[0],i=t.reduce(function(e,t,n){return 0==n%2?e+2*t%9||9:e+t},0);return i+=n,0==i%10},e.mapKeys=function(e,t){return Object.keys(e).reduce(function(n,i){return n[t(e[i],i,e)]=e[i],n},{})},e.mapObject=function(e,t){return function(n){return n=[e,e.map(t)],n[0].reduce(function(e,t,i){return e[t]=n[1][i],e},{})}()},e.mapString=function(e,t){return e.split('').map(function(n,r){return t(n,r,e)}).join('')},e.mapValues=function(e,t){return Object.keys(e).reduce(function(n,i){return n[i]=t(e[i],i,e),n},{})},e.mask=function(e){var t=1r-n&&(t='mouse',e(t),document.removeEventListener('mousemove',i)),n=r};document.addEventListener('touchstart',function(){'touch'==t||(t='touch',e(t),document.addEventListener('mousemove',i))})},e.once=function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,i=Array(n),r=0;rd?1:sj(e))return e+(i?' ':'')+r[0];var a=m(k(Math.log10(0>e?-e:e)/3),r.length-1),l=+((0>e?-e:e)/u(1e3,a)).toPrecision(t);return(0>e?'-':'')+l+(i?' ':'')+r[a]},e.primes=function(e){var t=Array.from({length:e-1}).map(function(e,t){return t+2}),n=k(g(e)),i=Array.from({length:n-1}).map(function(e,t){return t+2});return i.forEach(function(e){return t=t.filter(function(t){return 0!=t%e||t===e})}),t},e.promisify=function(e){return function(){for(var t=arguments.length,n=Array(t),i=0;ie[e.length-1],i=e.findIndex(function(e){return n?t>=e:t<=e});return-1===i?e.length:i},e.sortedIndexBy=function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.findIndex(function(e){return i?r>=n(e):r<=n(e)});return-1===a?e.length:a},e.sortedLastIndex=function(e,t){var n=e[0]>e[e.length-1],i=e.reverse().findIndex(function(e){return n?t<=e:t>=e});return-1===i?0:e.length-i},e.sortedLastIndexBy=function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.map(n).reverse().findIndex(function(e){return i?r<=e:r>=e});return-1===a?0:e.length-a},e.splitLines=function(e){return e.split(/\r?\n/)},e.spreadOver=function(e){return function(t){return e.apply(void 0,o(t))}},e.stableSort=function(e,t){return e.map(function(e,t){return{item:e,index:t}}).sort(function(e,n){return t(e.item,n.item)||e.index-n.index}).map(function(e){var t=e.item;return t})},e.standardDeviation=function(e){var t=!!(1=t.length?2===t.length?[t,t[1]+t[0]]:[t]:t.split('').reduce(function(n,r,a){return n.concat(e(t.slice(0,a)+t.slice(a+1)).map(function(e){return r+e}))},[])},e.stripHTMLTags=function(e){return e.replace(/<[^>]*>/g,'')},e.sum=function(){for(var e=arguments.length,t=Array(e),n=0;n=t&&(e.apply(a,l),r=Date.now())},_(t-(Date.now()-r),0))):(e.apply(a,l),r=Date.now(),n=!0)}},e.timeTaken=function(e){console.time('timeTaken');var t=e();return console.timeEnd('timeTaken'),t},e.times=function(e,t){for(var n=2t?e.slice(0,3r.length)throw new RangeError('Arguments too few!');return n(e)(r.slice(0,t))}},e.unescapeHTML=function(e){return e.replace(/&|<|>|'|"/g,function(e){return{"&":'&',"<":'<',">":'>',"'":'\'',""":'"'}[e]||e})},e.unflattenObject=function(e){return Object.keys(e).reduce(function(t,n){if(-1!==n.indexOf('.')){var r=n.split('.');Object.assign(t,JSON.parse('{'+r.map(function(e,t){return t===r.length-1?'"'.concat(e,'":'):'"'.concat(e,'":{')}).join('')+e[n]+'}'.repeat(r.length)))}else t[n]=e[n];return t},{})},e.unfold=function(e,t){for(var n=[],i=[null,t];i=e(i[1]);)n.push(i[0]);return n},e.union=function(e,t){return Array.from(new Set(o(e).concat(o(t))))},e.unionBy=function(e,t,n){var i=new Set(e.map(n));return Array.from(new Set(o(e).concat(o(t.filter(function(e){return!i.has(n(e))})))))},e.unionWith=function(e,t,n){return Array.from(new Set(o(e).concat(o(t.filter(function(t){return-1===e.findIndex(function(e){return n(t,e)})})))))},e.uniqueElements=function(e){return o(new Set(e))},e.uniqueElementsBy=function(e,t){return e.reduce(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},e.uniqueElementsByRight=function(e,t){return e.reduceRight(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},e.uniqueSymmetricDifference=function(e,t){return o(new Set(o(e.filter(function(e){return!t.includes(e)})).concat(o(t.filter(function(t){return!e.includes(t)})))))},e.untildify=function(e){return e.replace(/^~($|\/|\\)/,''.concat(require('os').homedir(),'$1'))},e.unzip=function(e){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:_.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]}))},e.unzipWith=function(e,t){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:_.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]})).map(function(e){return t.apply(void 0,o(e))})},e.validateNumber=function(e){return!isNaN(parseFloat(e))&&isFinite(e)&&+e==e},e.when=function(e,t){return function(n){return e(n)?t(n):n}},e.without=function(e){for(var t=arguments.length,n=Array(1'.concat(e,'')}).join('')}()},e.ary=function(e,t){return function(){for(var n=arguments.length,i=Array(n),r=0;rt||t>e)return 0;if(0===t||t===e)return 1;if(1===t||t===e-1)return e;e-t=(document.documentElement.scrollHeight||document.documentElement.clientHeight)},e.btoa=function(e){return Buffer.from(e,'binary').toString('base64')},e.byteSize=function(e){return new Blob([e]).size},e.call=function(e){for(var t=arguments.length,n=Array(1(n-t)*i?-i:i,o=setInterval(function(){a+=l,document.querySelector(e).innerHTML=a,a>=n&&(document.querySelector(e).innerHTML=n),a>=n&&clearInterval(o)},j(k(r/(n-t))));return o},e.countOccurrences=function(e,t){return e.reduce(function(e,n){return n===t?e+1:e},0)},e.createDirIfNotExists=function(e){return S.existsSync(e)?void 0:S.mkdirSync(e)},e.createElement=function(e){var t=document.createElement('div');return t.innerHTML=e,t.firstElementChild},e.createEventHub=function(){return{hub:Object.create(null),emit:function(e,t){(this.hub[e]||[]).forEach(function(e){return e(t)})},on:function(e,t){this.hub[e]||(this.hub[e]=[]),this.hub[e].push(t)},off:function(e,t){var n=(this.hub[e]||[]).findIndex(function(e){return e===t});-1'"]/g,function(e){return{"&":'&',"<":'<',">":'>',"'":''','"':'"'}[e]||e})},e.escapeRegExp=function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')},e.everyNth=function(e,t){return e.filter(function(n,e){return e%t==t-1})},e.extendHex=function(e){return'#'+e.slice(e.startsWith('#')?1:0).split('').map(function(e){return e+e}).join('')},e.factorial=function e(t){return 0>t?function(){throw new TypeError('Negative numbers are not allowed!')}():1>=t?1:t*e(t-1)},e.fibonacci=function(e){return Array.from({length:e}).reduce(function(e,t,n){return e.concat(1e&&(e=-e);var t={day:k(e/864e5),hour:k(e/36e5)%24,minute:k(e/6e4)%60,second:k(e/1e3)%60,millisecond:k(e)%1e3};return Object.entries(t).filter(function(e){return 0!==e[1]}).map(function(e){var t=r(e,2),n=t[0],i=t[1];return''.concat(i,' ').concat(n).concat(1===i?'':'s')}).join(', ')},e.forOwn=function(e,t){return Object.keys(e).forEach(function(n){return t(e[n],n,e)})},e.forOwnRight=function(e,t){return Object.keys(e).reverse().forEach(function(n){return t(e[n],n,e)})},e.fromCamelCase=function(e){var t=1e?e%12+'am':e%12+'pm'},e.getScrollPosition=function(){var e=0>>(t?24:16))+', '+((n&(t?16711680:65280))>>>(t?16:8))+', '+((n&(t?65280:255))>>>(t?8:0))+(t?', '.concat(255&n):'')+')'},e.hide=function(){for(var e=arguments.length,t=Array(e),n=0;nn){var i=[t,n];n=i[0],t=i[1]}return null==n?0<=e&&e=t&&et},e.isAnagram=function(e,t){var n=function(e){return e.toLowerCase().replace(/[^a-z0-9]/gi,'').split('').sort().join('')};return n(e)===n(t)},e.isArrayLike=function(e){return null!=e&&'function'==typeof e[Symbol.iterator]},e.isBeforeDate=function(e,t){return ee.length?t:e})},e.lowercaseKeys=function(e){return Object.keys(e).reduce(function(t,n){return t[n.toLowerCase()]=e[n],t},{})},e.luhnCheck=function(e){var t=(e+'').split('').reverse().map(function(e){return parseInt(e)}),n=t.splice(0,1)[0],i=t.reduce(function(e,t,n){return 0==n%2?e+2*t%9||9:e+t},0);return i+=n,0==i%10},e.mapKeys=function(e,t){return Object.keys(e).reduce(function(n,i){return n[t(e[i],i,e)]=e[i],n},{})},e.mapNumRange=function(e,t,n,i,r){return(e-t)*(r-i)/(n-t)+i},e.mapObject=function(e,t){return function(n){return n=[e,e.map(t)],n[0].reduce(function(e,t,i){return e[t]=n[1][i],e},{})}()},e.mapString=function(e,t){return e.split('').map(function(n,r){return t(n,r,e)}).join('')},e.mapValues=function(e,t){return Object.keys(e).reduce(function(n,i){return n[i]=t(e[i],i,e),n},{})},e.mask=function(e){var t=1r-n&&(t='mouse',e(t),document.removeEventListener('mousemove',i)),n=r};document.addEventListener('touchstart',function(){'touch'==t||(t='touch',e(t),document.addEventListener('mousemove',i))})},e.orderBy=function(e,t,n){return o(e).sort(function(e,a){return t.reduce(function(t,l,o){if(0===t){var i=n&&'desc'===n[o]?[a[l],e[l]]:[e[l],a[l]],c=r(i,2),s=c[0],d=c[1];t=s>d?1:sj(e))return e+(i?' ':'')+r[0];var a=m(k(Math.log10(0>e?-e:e)/3),r.length-1),l=+((0>e?-e:e)/u(1e3,a)).toPrecision(t);return(0>e?'-':'')+l+(i?' ':'')+r[a]},e.primes=function(e){var t=Array.from({length:e-1}).map(function(e,t){return t+2}),n=k(g(e)),i=Array.from({length:n-1}).map(function(e,t){return t+2});return i.forEach(function(e){return t=t.filter(function(t){return 0!=t%e||t===e})}),t},e.promisify=function(e){return function(){for(var t=arguments.length,n=Array(t),i=0;ie[e.length-1],i=e.findIndex(function(e){return n?t>=e:t<=e});return-1===i?e.length:i},e.sortedIndexBy=function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.findIndex(function(e){return i?r>=n(e):r<=n(e)});return-1===a?e.length:a},e.sortedLastIndex=function(e,t){var n=e[0]>e[e.length-1],i=e.reverse().findIndex(function(e){return n?t<=e:t>=e});return-1===i?0:e.length-i},e.sortedLastIndexBy=function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.map(n).reverse().findIndex(function(e){return i?r<=e:r>=e});return-1===a?0:e.length-a},e.splitLines=function(e){return e.split(/\r?\n/)},e.spreadOver=function(e){return function(t){return e.apply(void 0,o(t))}},e.stableSort=function(e,t){return e.map(function(e,t){return{item:e,index:t}}).sort(function(e,n){return t(e.item,n.item)||e.index-n.index}).map(function(e){var t=e.item;return t})},e.standardDeviation=function(e){var t=!!(1=t.length?2===t.length?[t,t[1]+t[0]]:[t]:t.split('').reduce(function(n,r,a){return n.concat(e(t.slice(0,a)+t.slice(a+1)).map(function(e){return r+e}))},[])},e.stripHTMLTags=function(e){return e.replace(/<[^>]*>/g,'')},e.sum=function(){for(var e=arguments.length,t=Array(e),n=0;n=t&&(e.apply(a,l),r=Date.now())},_(t-(Date.now()-r),0))):(e.apply(a,l),r=Date.now(),n=!0)}},e.times=function(e,t){for(var n=2t?e.slice(0,3r.length)throw new RangeError('Arguments too few!');return n(e)(r.slice(0,t))}},e.unescapeHTML=function(e){return e.replace(/&|<|>|'|"/g,function(e){return{"&":'&',"<":'<',">":'>',"'":'\'',""":'"'}[e]||e})},e.unflattenObject=function(e){return Object.keys(e).reduce(function(t,n){if(-1!==n.indexOf('.')){var r=n.split('.');Object.assign(t,JSON.parse('{'+r.map(function(e,t){return t===r.length-1?'"'.concat(e,'":'):'"'.concat(e,'":{')}).join('')+e[n]+'}'.repeat(r.length)))}else t[n]=e[n];return t},{})},e.unfold=function(e,t){for(var n=[],i=[null,t];i=e(i[1]);)n.push(i[0]);return n},e.union=function(e,t){return Array.from(new Set(o(e).concat(o(t))))},e.unionBy=function(e,t,n){var i=new Set(e.map(n));return Array.from(new Set(o(e).concat(o(t.filter(function(e){return!i.has(n(e))})))))},e.unionWith=function(e,t,n){return Array.from(new Set(o(e).concat(o(t.filter(function(t){return-1===e.findIndex(function(e){return n(t,e)})})))))},e.uniqueElements=function(e){return o(new Set(e))},e.uniqueElementsBy=function(e,t){return e.reduce(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},e.uniqueElementsByRight=function(e,t){return e.reduceRight(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},e.uniqueSymmetricDifference=function(e,t){return o(new Set(o(e.filter(function(e){return!t.includes(e)})).concat(o(t.filter(function(t){return!e.includes(t)})))))},e.untildify=function(e){return e.replace(/^~($|\/|\\)/,''.concat(require('os').homedir(),'$1'))},e.unzip=function(e){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:_.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]}))},e.unzipWith=function(e,t){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:_.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]})).map(function(e){return t.apply(void 0,o(e))})},e.URLJoin=function(){for(var e=arguments.length,t=Array(e),n=0;n>e/4).toString(16)})},e.UUIDGeneratorNode=function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(e){return(e^x.randomBytes(1)[0]&15>>e/4).toString(16)})},e.validateNumber=function(e){return!isNaN(parseFloat(e))&&isFinite(e)&&+e==e},e.when=function(e,t){return function(n){return e(n)?t(n):n}},e.without=function(e){for(var t=arguments.length,n=Array(1 - data - .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) - .split('\n') - .map(v => v.split(delimiter)); -const CSVToJSON = (data, delimiter = ',') => { - const titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data - .slice(data.indexOf('\n') + 1) - .split('\n') - .map(v => { - const values = v.split(delimiter); - return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); - }); -}; -const JSONToFile = (obj, filename) => - fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); -const JSONtoCSV = (arr, columns, delimiter = ',') => - [ - columns.join(delimiter), - ...arr.map(obj => - columns.reduce( - (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, - '' - ) - ) - ].join('\n'); -const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); -const URLJoin = (...args) => - args - .join('/') - .replace(/[\/]+/g, '/') - .replace(/^(.+):\//, '$1://') - .replace(/^file:/, 'file:/') - .replace(/\/(\?|&|#[^!])/g, '$1') - .replace(/\?/g, '&') - .replace('&', '?'); -const UUIDGeneratorBrowser = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) - ); -const UUIDGeneratorNode = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) - ); const all = (arr, fn = Boolean) => arr.every(fn); const allEqual = arr => arr.every(val => val === arr[0]); const any = (arr, fn = Boolean) => arr.some(fn); @@ -169,7 +124,6 @@ const countBy = (arr, fn) => acc[val] = (acc[val] || 0) + 1; return acc; }, {}); -const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); const counter = (selector, start, end, step = 1, duration = 2000) => { let current = start, _step = (end - start) * step < 0 ? -step : step, @@ -181,6 +135,7 @@ const counter = (selector, start, end, step = 1, duration = 2000) => { }, Math.abs(Math.floor(duration / (end - start)))); return timer; }; +const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); const createElement = str => { const el = document.createElement('div'); @@ -201,6 +156,21 @@ const createEventHub = () => ({ if (i > -1) this.hub[event].splice(i, 1); } }); +const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => + data + .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) + .split('\n') + .map(v => v.split(delimiter)); +const CSVToJSON = (data, delimiter = ',') => { + const titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data + .slice(data.indexOf('\n') + 1) + .split('\n') + .map(v => { + const values = v.split(delimiter); + return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); + }); +}; const currentURL = () => window.location.href; const curry = (fn, arity = fn.length, ...args) => arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); @@ -378,11 +348,6 @@ const forEachRight = (arr, callback) => .slice(0) .reverse() .forEach(callback); -const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); -const forOwnRight = (obj, fn) => - Object.keys(obj) - .reverse() - .forEach(key => fn(obj[key], key, obj)); const formatDuration = ms => { if (ms < 0) ms = -ms; const time = { @@ -397,6 +362,11 @@ const formatDuration = ms => { .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) .join(', '); }; +const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); +const forOwnRight = (obj, fn) => + Object.keys(obj) + .reverse() + .forEach(key => fn(obj[key], key, obj)); const fromCamelCase = (str, separator = '_') => str .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') @@ -525,10 +495,6 @@ const hz = (fn, iterations = 100) => { for (let i = 0; i < iterations; i++) fn(); return (1000 * iterations) / (performance.now() - before); }; -const inRange = (n, start, end = null) => { - if (end && start > end) [end, start] = [start, end]; - return end == null ? n >= 0 && n < start : n >= start && n < end; -}; const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); const initial = arr => arr.slice(0, -1); @@ -545,6 +511,10 @@ const initializeNDArray = (val, ...args) => args.length === 0 ? val : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); +const inRange = (n, start, end = null) => { + if (end && start > end) [end, start] = [start, end]; + return end == null ? n >= 0 && n < start : n >= start && n < end; +}; const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); const intersection = (a, b) => { @@ -656,6 +626,18 @@ const join = (arr, separator = ',', end = separator) => : acc + val + separator, '' ); +const JSONtoCSV = (arr, columns, delimiter = ',') => + [ + columns.join(delimiter), + ...arr.map(obj => + columns.reduce( + (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, + '' + ) + ) + ].join('\n'); +const JSONToFile = (obj, filename) => + fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); const last = arr => arr[arr.length - 1]; const lcm = (...arr) => { const gcd = (x, y) => (!y ? x : gcd(y, x % y)); @@ -683,6 +665,7 @@ const mapKeys = (obj, fn) => acc[fn(obj[k], k, obj)] = obj[k]; return acc; }, {}); +const mapNumRange = (num, inMin, inMax, outMin, outMax) => (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; const mapObject = (arr, fn) => (a => ( (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) @@ -788,6 +771,14 @@ const on = (el, evt, fn, opts = {}) => { el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); if (opts.target) return delegatorFn; }; +const once = fn => { + let called = false; + return function(...args) { + if (called) return; + called = true; + return fn.apply(this, args); + }; +}; const onUserInputChange = callback => { let type = 'mouse', lastTime = 0; @@ -802,14 +793,6 @@ const onUserInputChange = callback => { (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); }); }; -const once = fn => { - let called = false; - return function(...args) { - if (called) return; - called = true; - return fn.apply(this, args); - }; -}; const orderBy = (arr, props, orders) => [...arr].sort((a, b) => props.reduce((acc, prop, i) => { @@ -968,10 +951,6 @@ const recordAnimationFrames = (callback, autoStart = true) => { }; const redirect = (url, asLink = true) => asLink ? (window.location.href = url) : window.location.replace(url); -const reduceSuccessive = (arr, fn, acc) => - arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); -const reduceWhich = (arr, comparator = (a, b) => a - b) => - arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); const reducedFilter = (data, keys, fn) => data.filter(fn).map(el => keys.reduce((acc, key) => { @@ -979,6 +958,10 @@ const reducedFilter = (data, keys, fn) => return acc; }, {}) ); +const reduceSuccessive = (arr, fn, acc) => + arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); +const reduceWhich = (arr, comparator = (a, b) => a - b) => + arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); const reject = (pred, array) => array.filter((...args) => !pred(...args)); const remove = (arr, func) => Array.isArray(arr) @@ -997,6 +980,7 @@ const renameKeys = (keysMap, obj) => {} ); const reverseString = str => [...str].reverse().join(''); +const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); const runAsync = fn => { const worker = new Worker( @@ -1171,16 +1155,16 @@ const throttle = (fn, wait) => { } }; }; +const times = (n, fn, context = undefined) => { + let i = 0; + while (fn.call(context, i) !== false && ++i < n) {} +}; const timeTaken = callback => { console.time('timeTaken'); const r = callback(); console.timeEnd('timeTaken'); return r; }; -const times = (n, fn, context = undefined) => { - let i = 0; - while (fn.call(context, i) !== false && ++i < n) {} -}; const toCamelCase = str => { let s = str && @@ -1193,6 +1177,7 @@ const toCamelCase = str => { const toCurrency = (n, curr, LanguageFormat = undefined) => Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); const toDecimalMark = num => num.toLocaleString('en-US'); +const toggleClass = (el, className) => el.classList.toggle(className); const toHash = (object, key) => Array.prototype.reduce.call( object, @@ -1205,6 +1190,11 @@ const toKebabCase = str => .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.toLowerCase()) .join('-'); +const tomorrow = () => { + let t = new Date(); + t.setDate(t.getDate() + 1); + return t.toISOString().split('T')[0]; +}; const toOrdinalSuffix = num => { const int = parseInt(num), digits = [int % 10, int % 100], @@ -1228,12 +1218,6 @@ const toTitleCase = str => .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.charAt(0).toUpperCase() + x.slice(1)) .join(' '); -const toggleClass = (el, className) => el.classList.toggle(className); -const tomorrow = () => { - let t = new Date(); - t.setDate(t.getDate() + 1); - return t.toISOString().split('T')[0]; -}; const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); const triggerEvent = (el, eventType, detail) => el.dispatchEvent(new CustomEvent(eventType, { detail })); @@ -1318,6 +1302,23 @@ const unzipWith = (arr, fn) => }).map(x => []) ) .map(val => fn(...val)); +const URLJoin = (...args) => + args + .join('/') + .replace(/[\/]+/g, '/') + .replace(/^(.+):\//, '$1://') + .replace(/^file:/, 'file:/') + .replace(/\/(\?|&|#[^!])/g, '$1') + .replace(/\?/g, '&') + .replace('&', '?'); +const UUIDGeneratorBrowser = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) + ); +const UUIDGeneratorNode = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) + ); const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); const without = (arr, ...args) => arr.filter(v => !args.includes(v)); @@ -1341,4 +1342,4 @@ const zipWith = (...array) => { ); }; -export { CSVToArray, CSVToJSON, JSONToFile, JSONtoCSV, RGBToHex, URLJoin, UUIDGeneratorBrowser, UUIDGeneratorNode, all, allEqual, any, approximatelyEqual, arrayToCSV, arrayToHtmlList, ary, atob, attempt, average, averageBy, bifurcate, bifurcateBy, bind, bindAll, bindKey, binomialCoefficient, bottomVisible, btoa, byteSize, call, capitalize, capitalizeEveryWord, castArray, chainAsync, chunk, clampNumber, cloneRegExp, coalesce, coalesceFactory, collectInto, colorize, compact, compactWhitespace, compose, composeRight, converge, copyToClipboard, countBy, countOccurrences, counter, createDirIfNotExists, createElement, createEventHub, currentURL, curry, dayOfYear, debounce, decapitalize, deepClone, deepFlatten, deepFreeze, deepMapKeys, defaults, defer, degreesToRads, delay, detectDeviceType, difference, differenceBy, differenceWith, dig, digitize, distance, drop, dropRight, dropRightWhile, dropWhile, elementContains, elementIsVisibleInViewport, elo, equals, escapeHTML, escapeRegExp, everyNth, extendHex, factorial, fibonacci, filterFalsy, filterNonUnique, filterNonUniqueBy, findKey, findLast, findLastIndex, findLastKey, flatten, flattenObject, flip, forEachRight, forOwn, forOwnRight, formatDuration, fromCamelCase, functionName, functions, gcd, geometricProgression, get, getColonTimeFromDate, getDaysDiffBetweenDates, getImages, getMeridiemSuffixOfInteger, getScrollPosition, getStyle, getType, getURLParameters, groupBy, hammingDistance, hasClass, hasFlags, hashBrowser, hashNode, head, hexToRGB, hide, httpGet, httpPost, httpsRedirect, hz, inRange, indentString, indexOfAll, initial, initialize2DArray, initializeArrayWithRange, initializeArrayWithRangeRight, initializeArrayWithValues, initializeNDArray, insertAfter, insertBefore, intersection, intersectionBy, intersectionWith, invertKeyValues, is, isAbsoluteURL, isAfterDate, isAnagram, isArrayLike, isBeforeDate, isBoolean, isBrowser, isBrowserTabFocused, isDivisible, isDuplexStream, isEmpty, isEven, isFunction, isLowerCase, isNegativeZero, isNil, isNull, isNumber, isObject, isObjectLike, isPlainObject, isPrime, isPrimitive, isPromiseLike, isReadableStream, isSameDate, isSorted, isStream, isString, isSymbol, isTravisCI, isUndefined, isUpperCase, isValidJSON, isWritableStream, join, last, lcm, longestItem, lowercaseKeys, luhnCheck, mapKeys, mapObject, mapString, mapValues, mask, matches, matchesWith, maxBy, maxDate, maxN, median, memoize, merge, midpoint, minBy, minDate, minN, mostPerformant, negate, nest, nodeListToArray, none, nthArg, nthElement, objectFromPairs, objectToPairs, observeMutations, off, offset, omit, omitBy, on, onUserInputChange, once, orderBy, over, overArgs, pad, palindrome, parseCookie, partial, partialRight, partition, percentile, permutations, pick, pickBy, pipeAsyncFunctions, pipeFunctions, pluralize, powerset, prefix, prettyBytes, primes, promisify, pull, pullAtIndex, pullAtValue, pullBy, radsToDegrees, randomHexColorCode, randomIntArrayInRange, randomIntegerInRange, randomNumberInRange, readFileLines, rearg, recordAnimationFrames, redirect, reduceSuccessive, reduceWhich, reducedFilter, reject, remove, removeNonASCII, renameKeys, reverseString, round, runAsync, runPromisesInSeries, sample, sampleSize, scrollToTop, sdbm, serializeCookie, setStyle, shallowClone, shank, show, shuffle, similarity, size, sleep, smoothScroll, sortCharactersInString, sortedIndex, sortedIndexBy, sortedLastIndex, sortedLastIndexBy, splitLines, spreadOver, stableSort, standardDeviation, stringPermutations, stripHTMLTags, sum, sumBy, sumPower, symmetricDifference, symmetricDifferenceBy, symmetricDifferenceWith, tail, take, takeRight, takeRightWhile, takeWhile, throttle, timeTaken, times, toCamelCase, toCurrency, toDecimalMark, toHash, toKebabCase, toOrdinalSuffix, toSafeInteger, toSnakeCase, toTitleCase, toggleClass, tomorrow, transform, triggerEvent, truncateString, truthCheckCollection, unary, uncurry, unescapeHTML, unflattenObject, unfold, union, unionBy, unionWith, uniqueElements, uniqueElementsBy, uniqueElementsByRight, uniqueSymmetricDifference, untildify, unzip, unzipWith, validateNumber, when, without, words, xProd, yesNo, zip, zipObject, zipWith }; +export { all, allEqual, any, approximatelyEqual, arrayToCSV, arrayToHtmlList, ary, atob, attempt, average, averageBy, bifurcate, bifurcateBy, bind, bindAll, bindKey, binomialCoefficient, bottomVisible, btoa, byteSize, call, capitalize, capitalizeEveryWord, castArray, chainAsync, chunk, clampNumber, cloneRegExp, coalesce, coalesceFactory, collectInto, colorize, compact, compactWhitespace, compose, composeRight, converge, copyToClipboard, countBy, counter, countOccurrences, createDirIfNotExists, createElement, createEventHub, CSVToArray, CSVToJSON, currentURL, curry, dayOfYear, debounce, decapitalize, deepClone, deepFlatten, deepFreeze, deepMapKeys, defaults, defer, degreesToRads, delay, detectDeviceType, difference, differenceBy, differenceWith, dig, digitize, distance, drop, dropRight, dropRightWhile, dropWhile, elementContains, elementIsVisibleInViewport, elo, equals, escapeHTML, escapeRegExp, everyNth, extendHex, factorial, fibonacci, filterFalsy, filterNonUnique, filterNonUniqueBy, findKey, findLast, findLastIndex, findLastKey, flatten, flattenObject, flip, forEachRight, formatDuration, forOwn, forOwnRight, fromCamelCase, functionName, functions, gcd, geometricProgression, get, getColonTimeFromDate, getDaysDiffBetweenDates, getImages, getMeridiemSuffixOfInteger, getScrollPosition, getStyle, getType, getURLParameters, groupBy, hammingDistance, hasClass, hasFlags, hashBrowser, hashNode, head, hexToRGB, hide, httpGet, httpPost, httpsRedirect, hz, indentString, indexOfAll, initial, initialize2DArray, initializeArrayWithRange, initializeArrayWithRangeRight, initializeArrayWithValues, initializeNDArray, inRange, insertAfter, insertBefore, intersection, intersectionBy, intersectionWith, invertKeyValues, is, isAbsoluteURL, isAfterDate, isAnagram, isArrayLike, isBeforeDate, isBoolean, isBrowser, isBrowserTabFocused, isDivisible, isDuplexStream, isEmpty, isEven, isFunction, isLowerCase, isNegativeZero, isNil, isNull, isNumber, isObject, isObjectLike, isPlainObject, isPrime, isPrimitive, isPromiseLike, isReadableStream, isSameDate, isSorted, isStream, isString, isSymbol, isTravisCI, isUndefined, isUpperCase, isValidJSON, isWritableStream, join, JSONtoCSV, JSONToFile, last, lcm, longestItem, lowercaseKeys, luhnCheck, mapKeys, mapNumRange, mapObject, mapString, mapValues, mask, matches, matchesWith, maxBy, maxDate, maxN, median, memoize, merge, midpoint, minBy, minDate, minN, mostPerformant, negate, nest, nodeListToArray, none, nthArg, nthElement, objectFromPairs, objectToPairs, observeMutations, off, offset, omit, omitBy, on, once, onUserInputChange, orderBy, over, overArgs, pad, palindrome, parseCookie, partial, partialRight, partition, percentile, permutations, pick, pickBy, pipeAsyncFunctions, pipeFunctions, pluralize, powerset, prefix, prettyBytes, primes, promisify, pull, pullAtIndex, pullAtValue, pullBy, radsToDegrees, randomHexColorCode, randomIntArrayInRange, randomIntegerInRange, randomNumberInRange, readFileLines, rearg, recordAnimationFrames, redirect, reducedFilter, reduceSuccessive, reduceWhich, reject, remove, removeNonASCII, renameKeys, reverseString, RGBToHex, round, runAsync, runPromisesInSeries, sample, sampleSize, scrollToTop, sdbm, serializeCookie, setStyle, shallowClone, shank, show, shuffle, similarity, size, sleep, smoothScroll, sortCharactersInString, sortedIndex, sortedIndexBy, sortedLastIndex, sortedLastIndexBy, splitLines, spreadOver, stableSort, standardDeviation, stringPermutations, stripHTMLTags, sum, sumBy, sumPower, symmetricDifference, symmetricDifferenceBy, symmetricDifferenceWith, tail, take, takeRight, takeRightWhile, takeWhile, throttle, times, timeTaken, toCamelCase, toCurrency, toDecimalMark, toggleClass, toHash, toKebabCase, tomorrow, toOrdinalSuffix, toSafeInteger, toSnakeCase, toTitleCase, transform, triggerEvent, truncateString, truthCheckCollection, unary, uncurry, unescapeHTML, unflattenObject, unfold, union, unionBy, unionWith, uniqueElements, uniqueElementsBy, uniqueElementsByRight, uniqueSymmetricDifference, untildify, unzip, unzipWith, URLJoin, UUIDGeneratorBrowser, UUIDGeneratorNode, validateNumber, when, without, words, xProd, yesNo, zip, zipObject, zipWith }; diff --git a/dist/_30s.js b/dist/_30s.js index 6b906e92b..fcccfb7cf 100644 --- a/dist/_30s.js +++ b/dist/_30s.js @@ -7,51 +7,6 @@ const fs = typeof require !== "undefined" && require('fs'); const crypto = typeof require !== "undefined" && require('crypto'); - const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => - data - .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) - .split('\n') - .map(v => v.split(delimiter)); - const CSVToJSON = (data, delimiter = ',') => { - const titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data - .slice(data.indexOf('\n') + 1) - .split('\n') - .map(v => { - const values = v.split(delimiter); - return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); - }); - }; - const JSONToFile = (obj, filename) => - fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); - const JSONtoCSV = (arr, columns, delimiter = ',') => - [ - columns.join(delimiter), - ...arr.map(obj => - columns.reduce( - (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, - '' - ) - ) - ].join('\n'); - const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); - const URLJoin = (...args) => - args - .join('/') - .replace(/[\/]+/g, '/') - .replace(/^(.+):\//, '$1://') - .replace(/^file:/, 'file:/') - .replace(/\/(\?|&|#[^!])/g, '$1') - .replace(/\?/g, '&') - .replace('&', '?'); - const UUIDGeneratorBrowser = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) - ); - const UUIDGeneratorNode = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) - ); const all = (arr, fn = Boolean) => arr.every(fn); const allEqual = arr => arr.every(val => val === arr[0]); const any = (arr, fn = Boolean) => arr.some(fn); @@ -175,7 +130,6 @@ acc[val] = (acc[val] || 0) + 1; return acc; }, {}); - const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); const counter = (selector, start, end, step = 1, duration = 2000) => { let current = start, _step = (end - start) * step < 0 ? -step : step, @@ -187,6 +141,7 @@ }, Math.abs(Math.floor(duration / (end - start)))); return timer; }; + const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); const createElement = str => { const el = document.createElement('div'); @@ -207,6 +162,21 @@ if (i > -1) this.hub[event].splice(i, 1); } }); + const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => + data + .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) + .split('\n') + .map(v => v.split(delimiter)); + const CSVToJSON = (data, delimiter = ',') => { + const titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data + .slice(data.indexOf('\n') + 1) + .split('\n') + .map(v => { + const values = v.split(delimiter); + return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); + }); + }; const currentURL = () => window.location.href; const curry = (fn, arity = fn.length, ...args) => arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); @@ -384,11 +354,6 @@ .slice(0) .reverse() .forEach(callback); - const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); - const forOwnRight = (obj, fn) => - Object.keys(obj) - .reverse() - .forEach(key => fn(obj[key], key, obj)); const formatDuration = ms => { if (ms < 0) ms = -ms; const time = { @@ -403,6 +368,11 @@ .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) .join(', '); }; + const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); + const forOwnRight = (obj, fn) => + Object.keys(obj) + .reverse() + .forEach(key => fn(obj[key], key, obj)); const fromCamelCase = (str, separator = '_') => str .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') @@ -531,10 +501,6 @@ for (let i = 0; i < iterations; i++) fn(); return (1000 * iterations) / (performance.now() - before); }; - const inRange = (n, start, end = null) => { - if (end && start > end) [end, start] = [start, end]; - return end == null ? n >= 0 && n < start : n >= start && n < end; - }; const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); const initial = arr => arr.slice(0, -1); @@ -551,6 +517,10 @@ args.length === 0 ? val : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); + const inRange = (n, start, end = null) => { + if (end && start > end) [end, start] = [start, end]; + return end == null ? n >= 0 && n < start : n >= start && n < end; + }; const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); const intersection = (a, b) => { @@ -662,6 +632,18 @@ : acc + val + separator, '' ); + const JSONtoCSV = (arr, columns, delimiter = ',') => + [ + columns.join(delimiter), + ...arr.map(obj => + columns.reduce( + (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, + '' + ) + ) + ].join('\n'); + const JSONToFile = (obj, filename) => + fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); const last = arr => arr[arr.length - 1]; const lcm = (...arr) => { const gcd = (x, y) => (!y ? x : gcd(y, x % y)); @@ -689,6 +671,7 @@ acc[fn(obj[k], k, obj)] = obj[k]; return acc; }, {}); + const mapNumRange = (num, inMin, inMax, outMin, outMax) => (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; const mapObject = (arr, fn) => (a => ( (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) @@ -794,6 +777,14 @@ el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); if (opts.target) return delegatorFn; }; + const once = fn => { + let called = false; + return function(...args) { + if (called) return; + called = true; + return fn.apply(this, args); + }; + }; const onUserInputChange = callback => { let type = 'mouse', lastTime = 0; @@ -808,14 +799,6 @@ (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); }); }; - const once = fn => { - let called = false; - return function(...args) { - if (called) return; - called = true; - return fn.apply(this, args); - }; - }; const orderBy = (arr, props, orders) => [...arr].sort((a, b) => props.reduce((acc, prop, i) => { @@ -974,10 +957,6 @@ }; const redirect = (url, asLink = true) => asLink ? (window.location.href = url) : window.location.replace(url); - const reduceSuccessive = (arr, fn, acc) => - arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); - const reduceWhich = (arr, comparator = (a, b) => a - b) => - arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); const reducedFilter = (data, keys, fn) => data.filter(fn).map(el => keys.reduce((acc, key) => { @@ -985,6 +964,10 @@ return acc; }, {}) ); + const reduceSuccessive = (arr, fn, acc) => + arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); + const reduceWhich = (arr, comparator = (a, b) => a - b) => + arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); const reject = (pred, array) => array.filter((...args) => !pred(...args)); const remove = (arr, func) => Array.isArray(arr) @@ -1003,6 +986,7 @@ {} ); const reverseString = str => [...str].reverse().join(''); + const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); const runAsync = fn => { const worker = new Worker( @@ -1177,16 +1161,16 @@ } }; }; + const times = (n, fn, context = undefined) => { + let i = 0; + while (fn.call(context, i) !== false && ++i < n) {} + }; const timeTaken = callback => { console.time('timeTaken'); const r = callback(); console.timeEnd('timeTaken'); return r; }; - const times = (n, fn, context = undefined) => { - let i = 0; - while (fn.call(context, i) !== false && ++i < n) {} - }; const toCamelCase = str => { let s = str && @@ -1199,6 +1183,7 @@ const toCurrency = (n, curr, LanguageFormat = undefined) => Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); const toDecimalMark = num => num.toLocaleString('en-US'); + const toggleClass = (el, className) => el.classList.toggle(className); const toHash = (object, key) => Array.prototype.reduce.call( object, @@ -1211,6 +1196,11 @@ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.toLowerCase()) .join('-'); + const tomorrow = () => { + let t = new Date(); + t.setDate(t.getDate() + 1); + return t.toISOString().split('T')[0]; + }; const toOrdinalSuffix = num => { const int = parseInt(num), digits = [int % 10, int % 100], @@ -1234,12 +1224,6 @@ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.charAt(0).toUpperCase() + x.slice(1)) .join(' '); - const toggleClass = (el, className) => el.classList.toggle(className); - const tomorrow = () => { - let t = new Date(); - t.setDate(t.getDate() + 1); - return t.toISOString().split('T')[0]; - }; const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); const triggerEvent = (el, eventType, detail) => el.dispatchEvent(new CustomEvent(eventType, { detail })); @@ -1324,6 +1308,23 @@ }).map(x => []) ) .map(val => fn(...val)); + const URLJoin = (...args) => + args + .join('/') + .replace(/[\/]+/g, '/') + .replace(/^(.+):\//, '$1://') + .replace(/^file:/, 'file:/') + .replace(/\/(\?|&|#[^!])/g, '$1') + .replace(/\?/g, '&') + .replace('&', '?'); + const UUIDGeneratorBrowser = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) + ); + const UUIDGeneratorNode = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) + ); const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); const without = (arr, ...args) => arr.filter(v => !args.includes(v)); @@ -1347,14 +1348,6 @@ ); }; - exports.CSVToArray = CSVToArray; - exports.CSVToJSON = CSVToJSON; - exports.JSONToFile = JSONToFile; - exports.JSONtoCSV = JSONtoCSV; - exports.RGBToHex = RGBToHex; - exports.URLJoin = URLJoin; - exports.UUIDGeneratorBrowser = UUIDGeneratorBrowser; - exports.UUIDGeneratorNode = UUIDGeneratorNode; exports.all = all; exports.allEqual = allEqual; exports.any = any; @@ -1394,11 +1387,13 @@ exports.converge = converge; exports.copyToClipboard = copyToClipboard; exports.countBy = countBy; - exports.countOccurrences = countOccurrences; exports.counter = counter; + exports.countOccurrences = countOccurrences; exports.createDirIfNotExists = createDirIfNotExists; exports.createElement = createElement; exports.createEventHub = createEventHub; + exports.CSVToArray = CSVToArray; + exports.CSVToJSON = CSVToJSON; exports.currentURL = currentURL; exports.curry = curry; exports.dayOfYear = dayOfYear; @@ -1444,9 +1439,9 @@ exports.flattenObject = flattenObject; exports.flip = flip; exports.forEachRight = forEachRight; + exports.formatDuration = formatDuration; exports.forOwn = forOwn; exports.forOwnRight = forOwnRight; - exports.formatDuration = formatDuration; exports.fromCamelCase = fromCamelCase; exports.functionName = functionName; exports.functions = functions; @@ -1474,7 +1469,6 @@ exports.httpPost = httpPost; exports.httpsRedirect = httpsRedirect; exports.hz = hz; - exports.inRange = inRange; exports.indentString = indentString; exports.indexOfAll = indexOfAll; exports.initial = initial; @@ -1483,6 +1477,7 @@ exports.initializeArrayWithRangeRight = initializeArrayWithRangeRight; exports.initializeArrayWithValues = initializeArrayWithValues; exports.initializeNDArray = initializeNDArray; + exports.inRange = inRange; exports.insertAfter = insertAfter; exports.insertBefore = insertBefore; exports.intersection = intersection; @@ -1526,12 +1521,15 @@ exports.isValidJSON = isValidJSON; exports.isWritableStream = isWritableStream; exports.join = join; + exports.JSONtoCSV = JSONtoCSV; + exports.JSONToFile = JSONToFile; exports.last = last; exports.lcm = lcm; exports.longestItem = longestItem; exports.lowercaseKeys = lowercaseKeys; exports.luhnCheck = luhnCheck; exports.mapKeys = mapKeys; + exports.mapNumRange = mapNumRange; exports.mapObject = mapObject; exports.mapString = mapString; exports.mapValues = mapValues; @@ -1563,8 +1561,8 @@ exports.omit = omit; exports.omitBy = omitBy; exports.on = on; - exports.onUserInputChange = onUserInputChange; exports.once = once; + exports.onUserInputChange = onUserInputChange; exports.orderBy = orderBy; exports.over = over; exports.overArgs = overArgs; @@ -1599,14 +1597,15 @@ exports.rearg = rearg; exports.recordAnimationFrames = recordAnimationFrames; exports.redirect = redirect; + exports.reducedFilter = reducedFilter; exports.reduceSuccessive = reduceSuccessive; exports.reduceWhich = reduceWhich; - exports.reducedFilter = reducedFilter; exports.reject = reject; exports.remove = remove; exports.removeNonASCII = removeNonASCII; exports.renameKeys = renameKeys; exports.reverseString = reverseString; + exports.RGBToHex = RGBToHex; exports.round = round; exports.runAsync = runAsync; exports.runPromisesInSeries = runPromisesInSeries; @@ -1647,19 +1646,19 @@ exports.takeRightWhile = takeRightWhile; exports.takeWhile = takeWhile; exports.throttle = throttle; - exports.timeTaken = timeTaken; exports.times = times; + exports.timeTaken = timeTaken; exports.toCamelCase = toCamelCase; exports.toCurrency = toCurrency; exports.toDecimalMark = toDecimalMark; + exports.toggleClass = toggleClass; exports.toHash = toHash; exports.toKebabCase = toKebabCase; + exports.tomorrow = tomorrow; exports.toOrdinalSuffix = toOrdinalSuffix; exports.toSafeInteger = toSafeInteger; exports.toSnakeCase = toSnakeCase; exports.toTitleCase = toTitleCase; - exports.toggleClass = toggleClass; - exports.tomorrow = tomorrow; exports.transform = transform; exports.triggerEvent = triggerEvent; exports.truncateString = truncateString; @@ -1679,6 +1678,9 @@ exports.untildify = untildify; exports.unzip = unzip; exports.unzipWith = unzipWith; + exports.URLJoin = URLJoin; + exports.UUIDGeneratorBrowser = UUIDGeneratorBrowser; + exports.UUIDGeneratorNode = UUIDGeneratorNode; exports.validateNumber = validateNumber; exports.when = when; exports.without = without; diff --git a/snippets/mapNumRange.md b/snippets/mapNumRange.md index df12eb8ef..76c461b18 100644 --- a/snippets/mapNumRange.md +++ b/snippets/mapNumRange.md @@ -5,7 +5,7 @@ Maps a number from one range to another range. Returns `num` mapped between `outMin`-`outMax` from `inMin`-`inMax`. ```js -const distance = (num, inMin, inMax, outMin, outMax) => (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; +const mapNumRange = (num, inMin, inMax, outMin, outMax) => (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; ``` ```js diff --git a/test/_30s.js b/test/_30s.js index 0441f4c90..e70794e75 100644 --- a/test/_30s.js +++ b/test/_30s.js @@ -1,53 +1,6 @@ const fs = typeof require !== "undefined" && require('fs'); const crypto = typeof require !== "undefined" && require('crypto'); -const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => - data - .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) - .split('\n') - .map(v => v.split(delimiter)); -const CSVToJSON = (data, delimiter = ',') => { - const titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data - .slice(data.indexOf('\n') + 1) - .split('\n') - .map(v => { - const values = v.split(delimiter); - return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); - }); -}; - -const JSONToFile = (obj, filename) => - fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); -const JSONtoCSV = (arr, columns, delimiter = ',') => - [ - columns.join(delimiter), - ...arr.map(obj => - columns.reduce( - (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, - '' - ) - ) - ].join('\n'); -const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); -const URLJoin = (...args) => - args - .join('/') - .replace(/[\/]+/g, '/') - .replace(/^(.+):\//, '$1://') - .replace(/^file:/, 'file:/') - .replace(/\/(\?|&|#[^!])/g, '$1') - .replace(/\?/g, '&') - .replace('&', '?'); -const UUIDGeneratorBrowser = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) - ); - -const UUIDGeneratorNode = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) - ); const all = (arr, fn = Boolean) => arr.every(fn); const allEqual = arr => arr.every(val => val === arr[0]); const any = (arr, fn = Boolean) => arr.some(fn); @@ -60,7 +13,7 @@ const arrayToHtmlList = (arr, listID) => (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) ))(); const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); -const atob = str => Buffer.from(str, 'base64').toString('binary'); +const atob = str => Buffer.from(str, 'base64').toString('binary'); const attempt = (fn, ...args) => { try { return fn(...args); @@ -101,22 +54,22 @@ const binomialCoefficient = (n, k) => { const bottomVisible = () => document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight); -const btoa = str => Buffer.from(str, 'binary').toString('base64'); +const btoa = str => Buffer.from(str, 'binary').toString('base64'); const byteSize = str => new Blob([str]).size; const call = (key, ...args) => context => context[key](...args); const capitalize = ([first, ...rest], lowerRest = false) => first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); const castArray = val => (Array.isArray(val) ? val : [val]); -const chainAsync = fns => { - let curr = 0; - const last = fns[fns.length - 1]; - const next = () => { - const fn = fns[curr++]; - fn === last ? fn() : fn(next); - }; - next(); -}; +const chainAsync = fns => { + let curr = 0; + const last = fns[fns.length - 1]; + const next = () => { + const fn = fns[curr++]; + fn === last ? fn() : fn(next); + }; + next(); +}; const chunk = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size) @@ -145,8 +98,8 @@ const colorize = (...args) => ({ bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` }); const compact = arr => arr.filter(Boolean); -const compactWhitespace = str => str.replace(/\s{2,}/g, ' '); -const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); +const compactWhitespace = str => str.replace(/\s{2,}/g, ' '); +const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); const copyToClipboard = str => { @@ -166,12 +119,11 @@ const copyToClipboard = str => { document.getSelection().addRange(selected); } }; -const countBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { - acc[val] = (acc[val] || 0) + 1; - return acc; - }, {}); -const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); +const countBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { + acc[val] = (acc[val] || 0) + 1; + return acc; + }, {}); const counter = (selector, start, end, step = 1, duration = 2000) => { let current = start, _step = (end - start) * step < 0 ? -step : step, @@ -183,8 +135,9 @@ const counter = (selector, start, end, step = 1, duration = 2000) => { }, Math.abs(Math.floor(duration / (end - start)))); return timer; }; - -const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); +const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); + +const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); const createElement = str => { const el = document.createElement('div'); el.innerHTML = str; @@ -204,11 +157,26 @@ const createEventHub = () => ({ if (i > -1) this.hub[event].splice(i, 1); } }); +const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => + data + .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) + .split('\n') + .map(v => v.split(delimiter)); +const CSVToJSON = (data, delimiter = ',') => { + const titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data + .slice(data.indexOf('\n') + 1) + .split('\n') + .map(v => { + const values = v.split(delimiter); + return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); + }); +}; const currentURL = () => window.location.href; const curry = (fn, arity = fn.length, ...args) => arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); -const dayOfYear = date => - Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); +const dayOfYear = date => + Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); const debounce = (fn, ms = 0) => { let timeoutId; return function(...args) { @@ -218,38 +186,38 @@ const debounce = (fn, ms = 0) => { }; const decapitalize = ([first, ...rest], upperRest = false) => first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); -const deepClone = obj => { - let clone = Object.assign({}, obj); - Object.keys(clone).forEach( - key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) - ); - return Array.isArray(obj) && obj.length - ? (clone.length = obj.length) && Array.from(clone) - : Array.isArray(obj) - ? Array.from(obj) - : clone; -}; +const deepClone = obj => { + let clone = Object.assign({}, obj); + Object.keys(clone).forEach( + key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) + ); + return Array.isArray(obj) && obj.length + ? (clone.length = obj.length) && Array.from(clone) + : Array.isArray(obj) + ? Array.from(obj) + : clone; +}; const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); -const deepFreeze = obj => - Object.keys(obj).forEach( - prop => - !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) - ) || Object.freeze(obj); - -const deepMapKeys = (obj, f) => - Array.isArray(obj) - ? obj.map(val => deepMapKeys(val, f)) - : typeof obj === 'object' - ? Object.keys(obj).reduce((acc, current) => { - const val = obj[current]; - acc[f(current)] = - val !== null && typeof val === 'object' ? deepMapKeys(val, f) : (acc[f(current)] = val); - return acc; - }, {}) - : obj; +const deepFreeze = obj => + Object.keys(obj).forEach( + prop => + !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) + ) || Object.freeze(obj); + +const deepMapKeys = (obj, f) => + Array.isArray(obj) + ? obj.map(val => deepMapKeys(val, f)) + : typeof obj === 'object' + ? Object.keys(obj).reduce((acc, current) => { + const val = obj[current]; + acc[f(current)] = + val !== null && typeof val === 'object' ? deepMapKeys(val, f) : (acc[f(current)] = val); + return acc; + }, {}) + : obj; const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); -const defer = (fn, ...args) => setTimeout(fn, 1, ...args); -const degreesToRads = deg => (deg * Math.PI) / 180.0; +const defer = (fn, ...args) => setTimeout(fn, 1, ...args); +const degreesToRads = deg => (deg * Math.PI) / 180.0; const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); const detectDeviceType = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) @@ -259,19 +227,19 @@ const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); }; -const differenceBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => !s.has(fn(x))); -}; +const differenceBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => !s.has(fn(x))); +}; const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); - -const dig = (obj, target) => - target in obj - ? obj[target] - : Object.values(obj).reduce((acc, val) => { - if (acc !== undefined) return acc; - if (typeof val === 'object') return dig(val, target); - }, undefined); + +const dig = (obj, target) => + target in obj + ? obj[target] + : Object.values(obj).reduce((acc, val) => { + if (acc !== undefined) return acc; + if (typeof val === 'object') return dig(val, target); + }, undefined); const digitize = n => [...`${n}`].map(i => parseInt(i)); const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); const drop = (arr, n = 1) => arr.slice(n); @@ -293,22 +261,22 @@ const elementIsVisibleInViewport = (el, partiallyVisible = false) => { ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth; }; -const elo = ([...ratings], kFactor = 32, selfRating) => { - const [a, b] = ratings; - const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); - const newRating = (rating, i) => - (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); - if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; - - for (let i = 0, len = ratings.length; i < len; i++) { - let j = i; - while (j < len - 1) { - j++; - [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); - } - } - return ratings; -}; +const elo = ([...ratings], kFactor = 32, selfRating) => { + const [a, b] = ratings; + const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); + const newRating = (rating, i) => + (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); + if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; + + for (let i = 0, len = ratings.length; i < len; i++) { + let j = i; + while (j < len - 1) { + j++; + [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); + } + } + return ratings; +}; const equals = (a, b) => { if (a === b) return true; if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); @@ -340,15 +308,15 @@ const extendHex = shortHex => .split('') .map(x => x + x) .join(''); - -const factorial = n => - n < 0 - ? (() => { - throw new TypeError('Negative numbers are not allowed!'); - })() - : n <= 1 - ? 1 - : n * factorial(n - 1); + +const factorial = n => + n < 0 + ? (() => { + throw new TypeError('Negative numbers are not allowed!'); + })() + : n <= 1 + ? 1 + : n * factorial(n - 1); const fibonacci = n => Array.from({ length: n }).reduce( (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), @@ -384,11 +352,6 @@ const forEachRight = (arr, callback) => .slice(0) .reverse() .forEach(callback); -const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); -const forOwnRight = (obj, fn) => - Object.keys(obj) - .reverse() - .forEach(key => fn(obj[key], key, obj)); const formatDuration = ms => { if (ms < 0) ms = -ms; const time = { @@ -403,6 +366,11 @@ const formatDuration = ms => { .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) .join(', '); }; +const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); +const forOwnRight = (obj, fn) => + Object.keys(obj) + .reverse() + .forEach(key => fn(obj[key], key, obj)); const fromCamelCase = (str, separator = '_') => str .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') @@ -430,21 +398,21 @@ const get = (from, ...selectors) => .filter(t => t !== '') .reduce((prev, cur) => prev && prev[cur], from) ); -const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); +const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24); -const getImages = (el, includeDuplicates = false) => { - const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); - return includeDuplicates ? images : [...new Set(images)]; -}; -const getMeridiemSuffixOfInteger = num => - num === 0 || num === 24 - ? 12 + 'am' - : num === 12 - ? 12 + 'pm' - : num < 12 - ? (num % 12) + 'am' - : (num % 12) + 'pm'; +const getImages = (el, includeDuplicates = false) => { + const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); + return includeDuplicates ? images : [...new Set(images)]; +}; +const getMeridiemSuffixOfInteger = num => + num === 0 || num === 24 + ? 12 + 'am' + : num === 12 + ? 12 + 'pm' + : num < 12 + ? (num % 12) + 'am' + : (num % 12) + 'pm'; const getScrollPosition = (el = window) => ({ x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop @@ -474,20 +442,20 @@ const hashBrowser = val => hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8)); return hexes.join(''); }); - -const hashNode = val => - new Promise(resolve => - setTimeout( - () => - resolve( - crypto - .createHash('sha256') - .update(val) - .digest('hex') - ), - 0 - ) - ); + +const hashNode = val => + new Promise(resolve => + setTimeout( + () => + resolve( + crypto + .createHash('sha256') + .update(val) + .digest('hex') + ), + 0 + ) + ); const head = arr => arr[0]; const hexToRGB = hex => { let alpha = false, @@ -508,34 +476,30 @@ const hexToRGB = hex => { ')' ); }; -const hide = (...el) => [...el].forEach(e => (e.style.display = 'none')); -const httpGet = (url, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('GET', url, true); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(); -}; -const httpPost = (url, data, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('POST', url, true); - request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(data); -}; +const hide = (...el) => [...el].forEach(e => (e.style.display = 'none')); +const httpGet = (url, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('GET', url, true); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(); +}; +const httpPost = (url, data, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('POST', url, true); + request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(data); +}; const httpsRedirect = () => { if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); }; -const hz = (fn, iterations = 100) => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return (1000 * iterations) / (performance.now() - before); -}; -const inRange = (n, start, end = null) => { - if (end && start > end) [end, start] = [start, end]; - return end == null ? n >= 0 && n < start : n >= start && n < end; -}; +const hz = (fn, iterations = 100) => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return (1000 * iterations) / (performance.now() - before); +}; const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); const initial = arr => arr.slice(0, -1); @@ -552,6 +516,10 @@ const initializeNDArray = (val, ...args) => args.length === 0 ? val : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); +const inRange = (n, start, end = null) => { + if (end && start > end) [end, start] = [start, end]; + return end == null ? n >= 0 && n < start : n >= start && n < end; +}; const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); const intersection = (a, b) => { @@ -572,7 +540,7 @@ const invertKeyValues = (obj, fn) => }, {}); const is = (type, val) => ![, null].includes(val) && val.constructor === type; const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); -const isAfterDate = (dateA, dateB) => dateA > dateB; +const isAfterDate = (dateA, dateB) => dateA > dateB; const isAnagram = (str1, str2) => { const normalize = str => str @@ -584,24 +552,24 @@ const isAnagram = (str1, str2) => { return normalize(str1) === normalize(str2); }; const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; -const isBeforeDate = (dateA, dateB) => dateA < dateB; +const isBeforeDate = (dateA, dateB) => dateA < dateB; const isBoolean = val => typeof val === 'boolean'; const isBrowser = () => ![typeof window, typeof document].includes('undefined'); const isBrowserTabFocused = () => !document.hidden; const isDivisible = (dividend, divisor) => dividend % divisor === 0; -const isDuplexStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; +const isDuplexStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; const isEmpty = val => val == null || !(Object.keys(val) || val).length; const isEven = num => num % 2 === 0; const isFunction = val => typeof val === 'function'; const isLowerCase = str => str === str.toLowerCase(); -const isNegativeZero = val => val === 0 && 1 / val === -Infinity; +const isNegativeZero = val => val === 0 && 1 / val === -Infinity; const isNil = val => val === undefined || val === null; const isNull = val => val === null; const isNumber = val => typeof val === 'number'; @@ -613,18 +581,18 @@ const isPrime = num => { for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; return num >= 2; }; -const isPrimitive = val => Object(val) !== val; +const isPrimitive = val => Object(val) !== val; const isPromiseLike = obj => obj !== null && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'; -const isReadableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object'; -const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); +const isReadableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object'; +const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); const isSorted = arr => { let direction = -(arr[0] - arr[1]); for (let [i, val] of arr.entries()) { @@ -633,26 +601,26 @@ const isSorted = arr => { else if ((val - arr[i + 1]) * direction > 0) return 0; } }; -const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; -const isString = val => typeof val === 'string'; +const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; +const isString = val => typeof val === 'string'; const isSymbol = val => typeof val === 'symbol'; const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; const isUndefined = val => val === undefined; const isUpperCase = str => str === str.toUpperCase(); -const isValidJSON = str => { - try { - JSON.parse(str); - return true; - } catch (e) { - return false; - } -}; -const isWritableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; +const isValidJSON = str => { + try { + JSON.parse(str); + return true; + } catch (e) { + return false; + } +}; +const isWritableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; const join = (arr, separator = ',', end = separator) => arr.reduce( (acc, val, i) => @@ -663,33 +631,47 @@ const join = (arr, separator = ',', end = separator) => : acc + val + separator, '' ); +const JSONtoCSV = (arr, columns, delimiter = ',') => + [ + columns.join(delimiter), + ...arr.map(obj => + columns.reduce( + (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, + '' + ) + ) + ].join('\n'); + +const JSONToFile = (obj, filename) => + fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); const last = arr => arr[arr.length - 1]; -const lcm = (...arr) => { - const gcd = (x, y) => (!y ? x : gcd(y, x % y)); - const _lcm = (x, y) => (x * y) / gcd(x, y); - return [...arr].reduce((a, b) => _lcm(a, b)); -}; -const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a)); +const lcm = (...arr) => { + const gcd = (x, y) => (!y ? x : gcd(y, x % y)); + const _lcm = (x, y) => (x * y) / gcd(x, y); + return [...arr].reduce((a, b) => _lcm(a, b)); +}; +const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a)); const lowercaseKeys = obj => Object.keys(obj).reduce((acc, key) => { acc[key.toLowerCase()] = obj[key]; return acc; }, {}); -const luhnCheck = num => { - let arr = (num + '') - .split('') - .reverse() - .map(x => parseInt(x)); - let lastDigit = arr.splice(0, 1)[0]; - let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); - sum += lastDigit; - return sum % 10 === 0; -}; +const luhnCheck = num => { + let arr = (num + '') + .split('') + .reverse() + .map(x => parseInt(x)); + let lastDigit = arr.splice(0, 1)[0]; + let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); + sum += lastDigit; + return sum % 10 === 0; +}; const mapKeys = (obj, fn) => Object.keys(obj).reduce((acc, k) => { acc[fn(obj[k], k, obj)] = obj[k]; return acc; }, {}); + const mapNumRange = (num, inMin, inMax, outMin, outMax) => (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; const mapObject = (arr, fn) => (a => ( (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) @@ -715,7 +697,7 @@ const matchesWith = (obj, source, fn) => : obj[key] == source[key] ); const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); -const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); +const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); const median = arr => { const mid = Math.floor(arr.length / 2), @@ -739,9 +721,9 @@ const merge = (...objs) => }, {}), {} ); -const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2]; +const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2]; const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); -const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); +const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); const mostPerformant = (fns, iterations = 10000) => { const times = fns.map(fn => { @@ -795,6 +777,14 @@ const on = (el, evt, fn, opts = {}) => { el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); if (opts.target) return delegatorFn; }; +const once = fn => { + let called = false; + return function(...args) { + if (called) return; + called = true; + return fn.apply(this, args); + }; +}; const onUserInputChange = callback => { let type = 'mouse', lastTime = 0; @@ -809,14 +799,6 @@ const onUserInputChange = callback => { (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); }); }; -const once = fn => { - let called = false; - return function(...args) { - if (called) return; - called = true; - return fn.apply(this, args); - }; -}; const orderBy = (arr, props, orders) => [...arr].sort((a, b) => props.reduce((acc, prop, i) => { @@ -831,10 +813,10 @@ const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); const pad = (str, length, char = ' ') => str.padStart((str.length + length) / 2, char).padEnd(length, char); -const palindrome = str => { - const s = str.toLowerCase().replace(/[\W_]/g, ''); - return s === [...s].reverse().join(''); -}; +const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g, ''); + return s === [...s].reverse().join(''); +}; const parseCookie = str => str .split(';') @@ -853,8 +835,8 @@ const partition = (arr, fn) => }, [[], []] ); -const percentile = (arr, val) => - (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; +const percentile = (arr, val) => + (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; const permutations = arr => { if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; return arr.reduce( @@ -871,7 +853,7 @@ const pickBy = (obj, fn) => Object.keys(obj) .filter(k => fn(obj[k], k)) .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); -const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); + const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); const pluralize = (val, word, plural = word + 's') => { const _pluralize = (num, word, plural = word + 's') => @@ -938,7 +920,7 @@ const pullBy = (arr, ...args) => { arr.length = 0; pulled.forEach(v => arr.push(v)); }; -const radsToDegrees = rad => (rad * 180.0) / Math.PI; +const radsToDegrees = rad => (rad * 180.0) / Math.PI; const randomHexColorCode = () => { let n = (Math.random() * 0xfffff * 1000000).toString(16); return '#' + n.slice(0, 6); @@ -976,10 +958,6 @@ const recordAnimationFrames = (callback, autoStart = true) => { }; const redirect = (url, asLink = true) => asLink ? (window.location.href = url) : window.location.replace(url); -const reduceSuccessive = (arr, fn, acc) => - arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); -const reduceWhich = (arr, comparator = (a, b) => a - b) => - arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); const reducedFilter = (data, keys, fn) => data.filter(fn).map(el => keys.reduce((acc, key) => { @@ -987,15 +965,19 @@ const reducedFilter = (data, keys, fn) => return acc; }, {}) ); +const reduceSuccessive = (arr, fn, acc) => + arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); +const reduceWhich = (arr, comparator = (a, b) => a - b) => + arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); const reject = (pred, array) => array.filter((...args) => !pred(...args)); - -const remove = (arr, func) => - Array.isArray(arr) - ? arr.filter(func).reduce((acc, val) => { - arr.splice(arr.indexOf(val), 1); - return acc.concat(val); - }, []) - : []; + +const remove = (arr, func) => + Array.isArray(arr) + ? arr.filter(func).reduce((acc, val) => { + arr.splice(arr.indexOf(val), 1); + return acc.concat(val); + }, []) + : []; const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); const renameKeys = (keysMap, obj) => Object.keys(obj).reduce( @@ -1006,24 +988,25 @@ const renameKeys = (keysMap, obj) => {} ); const reverseString = str => [...str].reverse().join(''); +const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); -const runAsync = fn => { - const worker = new Worker( - URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { - type: 'application/javascript; charset=utf-8' - }) - ); - return new Promise((res, rej) => { - worker.onmessage = ({ data }) => { - res(data), worker.terminate(); - }; - worker.onerror = err => { - rej(err), worker.terminate(); - }; - }); -}; +const runAsync = fn => { + const worker = new Worker( + URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { + type: 'application/javascript; charset=utf-8' + }) + ); + return new Promise((res, rej) => { + worker.onmessage = ({ data }) => { + res(data), worker.terminate(); + }; + worker.onerror = err => { + rej(err), worker.terminate(); + }; + }); +}; const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); -const sample = arr => arr[Math.floor(Math.random() * arr.length)]; +const sample = arr => arr[Math.floor(Math.random() * arr.length)]; const sampleSize = ([...arr], n = 1) => { let m = arr.length; while (m) { @@ -1050,11 +1033,11 @@ const sdbm = str => { const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); const shallowClone = obj => Object.assign({}, obj); -const shank = (arr, index = 0, delCount = 0, ...elements) => - arr - .slice(0, index) - .concat(elements) - .concat(arr.slice(index + delCount)); +const shank = (arr, index = 0, delCount = 0, ...elements) => + arr + .slice(0, index) + .concat(elements) + .concat(arr.slice(index + delCount)); const show = (...el) => [...el].forEach(e => (e.style.display = '')); const shuffle = ([...arr]) => { let m = arr.length; @@ -1129,14 +1112,14 @@ const stringPermutations = str => { ); }; const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); -const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); +const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); const sumBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); -const sumPower = (end, power = 2, start = 1) => - Array(end + 1 - start) - .fill(0) - .map((x, i) => (i + start) ** power) - .reduce((a, b) => a + b, 0); +const sumPower = (end, power = 2, start = 1) => + Array(end + 1 - start) + .fill(0) + .map((x, i) => (i + start) ** power) + .reduce((a, b) => a + b, 0); const symmetricDifference = (a, b) => { const sA = new Set(a), sB = new Set(b); @@ -1154,31 +1137,35 @@ const symmetricDifferenceWith = (arr, val, comp) => [ const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); const take = (arr, n = 1) => arr.slice(0, n); const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); -const takeRightWhile = (arr, func) => - arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); +const takeRightWhile = (arr, func) => + arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); const takeWhile = (arr, func) => { for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); return arr; }; -const throttle = (fn, wait) => { - let inThrottle, lastFn, lastTime; - return function() { - const context = this, - args = arguments; - if (!inThrottle) { - fn.apply(context, args); - lastTime = Date.now(); - inThrottle = true; - } else { - clearTimeout(lastFn); - lastFn = setTimeout(function() { - if (Date.now() - lastTime >= wait) { - fn.apply(context, args); - lastTime = Date.now(); - } - }, Math.max(wait - (Date.now() - lastTime), 0)); - } - }; +const throttle = (fn, wait) => { + let inThrottle, lastFn, lastTime; + return function() { + const context = this, + args = arguments; + if (!inThrottle) { + fn.apply(context, args); + lastTime = Date.now(); + inThrottle = true; + } else { + clearTimeout(lastFn); + lastFn = setTimeout(function() { + if (Date.now() - lastTime >= wait) { + fn.apply(context, args); + lastTime = Date.now(); + } + }, Math.max(wait - (Date.now() - lastTime), 0)); + } + }; +}; +const times = (n, fn, context = undefined) => { + let i = 0; + while (fn.call(context, i) !== false && ++i < n) {} }; const timeTaken = callback => { console.time('timeTaken'); @@ -1186,10 +1173,6 @@ const timeTaken = callback => { console.timeEnd('timeTaken'); return r; }; -const times = (n, fn, context = undefined) => { - let i = 0; - while (fn.call(context, i) !== false && ++i < n) {} -}; const toCamelCase = str => { let s = str && @@ -1202,18 +1185,24 @@ const toCamelCase = str => { const toCurrency = (n, curr, LanguageFormat = undefined) => Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); const toDecimalMark = num => num.toLocaleString('en-US'); -const toHash = (object, key) => - Array.prototype.reduce.call( - object, - (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), - {} - ); +const toggleClass = (el, className) => el.classList.toggle(className); +const toHash = (object, key) => + Array.prototype.reduce.call( + object, + (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), + {} + ); const toKebabCase = str => str && str .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.toLowerCase()) .join('-'); +const tomorrow = () => { + let t = new Date(); + t.setDate(t.getDate() + 1); + return t.toISOString().split('T')[0]; +}; const toOrdinalSuffix = num => { const int = parseInt(num), digits = [int % 10, int % 100], @@ -1232,20 +1221,14 @@ const toSnakeCase = str => .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.toLowerCase()) .join('_'); -const toTitleCase = str => - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.charAt(0).toUpperCase() + x.slice(1)) - .join(' '); -const toggleClass = (el, className) => el.classList.toggle(className); -const tomorrow = () => { - let t = new Date(); - t.setDate(t.getDate() + 1); - return t.toISOString().split('T')[0]; -}; +const toTitleCase = str => + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.charAt(0).toUpperCase() + x.slice(1)) + .join(' '); const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); -const triggerEvent = (el, eventType, detail) => - el.dispatchEvent(new CustomEvent(eventType, { detail })); +const triggerEvent = (el, eventType, detail) => + el.dispatchEvent(new CustomEvent(eventType, { detail })); const truncateString = (str, num) => str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); @@ -1290,10 +1273,10 @@ const unfold = (fn, seed) => { return result; }; const union = (a, b) => Array.from(new Set([...a, ...b])); -const unionBy = (a, b, fn) => { - const s = new Set(a.map(fn)); - return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); -}; +const unionBy = (a, b, fn) => { + const s = new Set(a.map(fn)); + return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); +}; const unionWith = (a, b, comp) => Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); const uniqueElements = arr => [...new Set(arr)]; @@ -1311,13 +1294,13 @@ const uniqueSymmetricDifference = (a, b) => [ ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) ]; const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); -const unzip = arr => - arr.reduce( - (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), - Array.from({ - length: Math.max(...arr.map(x => x.length)) - }).map(x => []) - ); +const unzip = arr => + arr.reduce( + (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), + Array.from({ + length: Math.max(...arr.map(x => x.length)) + }).map(x => []) + ); const unzipWith = (arr, fn) => arr .reduce( @@ -1327,6 +1310,24 @@ const unzipWith = (arr, fn) => }).map(x => []) ) .map(val => fn(...val)); +const URLJoin = (...args) => + args + .join('/') + .replace(/[\/]+/g, '/') + .replace(/^(.+):\//, '$1://') + .replace(/^file:/, 'file:/') + .replace(/\/(\?|&|#[^!])/g, '$1') + .replace(/\?/g, '&') + .replace('&', '?'); +const UUIDGeneratorBrowser = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) + ); + +const UUIDGeneratorNode = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) + ); const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); const without = (arr, ...args) => arr.filter(v => !args.includes(v)); @@ -1349,170 +1350,170 @@ const zipWith = (...array) => { (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])) ); }; -const JSONToDate = arr => { - const dt = new Date(parseInt(arr.toString().substr(6))); - return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`; -}; -const binarySearch = (arr, val, start = 0, end = arr.length - 1) => { - if (start > end) return -1; - const mid = Math.floor((start + end) / 2); - if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1); - if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end); - return mid; -}; -const celsiusToFahrenheit = degrees => 1.8 * degrees + 32; -const cleanObj = (obj, keysToKeep = [], childIndicator) => { - Object.keys(obj).forEach(key => { - if (key === childIndicator) { - cleanObj(obj[key], keysToKeep, childIndicator); - } else if (!keysToKeep.includes(key)) { - delete obj[key]; - } - }); - return obj; -}; -const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1); -const countVowels = str => (str.match(/[aeiou]/gi) || []).length; -const factors = (num, primes = false) => { - const isPrime = num => { - const boundary = Math.floor(Math.sqrt(num)); - for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; - return num >= 2; - }; - const isNeg = num < 0; - num = isNeg ? -num : num; - let array = Array.from({ length: num - 1 }) - .map((val, i) => (num % (i + 2) === 0 ? i + 2 : false)) - .filter(val => val); - if (isNeg) - array = array.reduce((acc, val) => { - acc.push(val); - acc.push(-val); - return acc; - }, []); - return primes ? array.filter(isPrime) : array; -}; -const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9; -const fibonacciCountUntilNum = num => - Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2)); -const fibonacciUntilNum = num => { - let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2)); - return Array.from({ length: n }).reduce( - (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), - [] - ); -}; -const heronArea = (side_a, side_b, side_c) => { - const p = (side_a + side_b + side_c) / 2 - return Math.sqrt(p * (p-side_a) * (p-side_b) * (p-side_c)) - }; -const howManyTimes = (num, divisor) => { - if (divisor === 1 || divisor === -1) return Infinity; - if (divisor === 0) return 0; - let i = 0; - while (Number.isInteger(num / divisor)) { - i++; - num = num / divisor; - } - return i; -}; -const httpDelete = (url, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('DELETE', url, true); - request.onload = () => callback(request); - request.onerror = () => err(request); - request.send(); -}; -const httpPut = (url, data, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open("PUT", url, true); - request.setRequestHeader('Content-type','application/json; charset=utf-8'); - request.onload = () => callback(request); - request.onerror = () => err(request); - request.send(data); -}; -const isArmstrongNumber = digits => - (arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)( - (digits + '').split('') - ); -const isSimilar = (pattern, str) => - [...str].reduce( - (matchIndex, char) => - char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() - ? matchIndex + 1 - : matchIndex, - 0 - ) === pattern.length; -const kmphToMph = (kmph) => 0.621371192 * kmph; -const levenshteinDistance = (string1, string2) => { - if (string1.length === 0) return string2.length; - if (string2.length === 0) return string1.length; - let matrix = Array(string2.length + 1) - .fill(0) - .map((x, i) => [i]); - matrix[0] = Array(string1.length + 1) - .fill(0) - .map((x, i) => i); - for (let i = 1; i <= string2.length; i++) { - for (let j = 1; j <= string1.length; j++) { - if (string2[i - 1] === string1[j - 1]) { - matrix[i][j] = matrix[i - 1][j - 1]; - } else { - matrix[i][j] = Math.min( - matrix[i - 1][j - 1] + 1, - matrix[i][j - 1] + 1, - matrix[i - 1][j] + 1 - ); - } - } - } - return matrix[string2.length][string1.length]; -}; -const mphToKmph = (mph) => 1.6093440006146922 * mph; -const pipeLog = data => console.log(data) || data; -const quickSort = ([n, ...nums], desc) => - isNaN(n) - ? [] - : [ - ...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc), - n, - ...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc) - ]; -const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi, repl); -const solveRPN = rpn => { - const OPERATORS = { - '*': (a, b) => a * b, - '+': (a, b) => a + b, - '-': (a, b) => a - b, - '/': (a, b) => a / b, - '**': (a, b) => a ** b - }; - const [stack, solve] = [ - [], - rpn - .replace(/\^/g, '**') - .split(/\s+/g) - .filter(el => !/\s+/.test(el) && el !== '') - ]; - solve.forEach(symbol => { - if (!isNaN(parseFloat(symbol)) && isFinite(symbol)) { - stack.push(symbol); - } else if (Object.keys(OPERATORS).includes(symbol)) { - const [a, b] = [stack.pop(), stack.pop()]; - stack.push(OPERATORS[symbol](parseFloat(b), parseFloat(a))); - } else { - throw `${symbol} is not a recognized symbol`; - } - }); - if (stack.length === 1) return stack.pop(); - else throw `${rpn} is not a proper RPN. Please check it and try again`; -}; -const speechSynthesis = message => { - const msg = new SpeechSynthesisUtterance(message); - msg.voice = window.speechSynthesis.getVoices()[0]; - window.speechSynthesis.speak(msg); -}; -const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0); + const binarySearch = (arr, val, start = 0, end = arr.length - 1) => { + if (start > end) return -1; + const mid = Math.floor((start + end) / 2); + if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1); + if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end); + return mid; +}; + const celsiusToFahrenheit = degrees => 1.8 * degrees + 32; + const cleanObj = (obj, keysToKeep = [], childIndicator) => { + Object.keys(obj).forEach(key => { + if (key === childIndicator) { + cleanObj(obj[key], keysToKeep, childIndicator); + } else if (!keysToKeep.includes(key)) { + delete obj[key]; + } + }); + return obj; +}; + const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1); + const countVowels = str => (str.match(/[aeiou]/gi) || []).length; + const factors = (num, primes = false) => { + const isPrime = num => { + const boundary = Math.floor(Math.sqrt(num)); + for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; + return num >= 2; + }; + const isNeg = num < 0; + num = isNeg ? -num : num; + let array = Array.from({ length: num - 1 }) + .map((val, i) => (num % (i + 2) === 0 ? i + 2 : false)) + .filter(val => val); + if (isNeg) + array = array.reduce((acc, val) => { + acc.push(val); + acc.push(-val); + return acc; + }, []); + return primes ? array.filter(isPrime) : array; +}; + const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9; + const fibonacciCountUntilNum = num => + Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2)); + const fibonacciUntilNum = num => { + let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2)); + return Array.from({ length: n }).reduce( + (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), + [] + ); +}; + const heronArea = (side_a, side_b, side_c) => { + const p = (side_a + side_b + side_c) / 2 + return Math.sqrt(p * (p-side_a) * (p-side_b) * (p-side_c)) + }; + const howManyTimes = (num, divisor) => { + if (divisor === 1 || divisor === -1) return Infinity; + if (divisor === 0) return 0; + let i = 0; + while (Number.isInteger(num / divisor)) { + i++; + num = num / divisor; + } + return i; +}; + const httpDelete = (url, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('DELETE', url, true); + request.onload = () => callback(request); + request.onerror = () => err(request); + request.send(); +}; + const httpPut = (url, data, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open("PUT", url, true); + request.setRequestHeader('Content-type','application/json; charset=utf-8'); + request.onload = () => callback(request); + request.onerror = () => err(request); + request.send(data); +}; + const isArmstrongNumber = digits => + (arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)( + (digits + '').split('') + ); + const isSimilar = (pattern, str) => + [...str].reduce( + (matchIndex, char) => + char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() + ? matchIndex + 1 + : matchIndex, + 0 + ) === pattern.length; + const JSONToDate = arr => { + const dt = new Date(parseInt(arr.toString().substr(6))); + return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`; +}; + const kmphToMph = (kmph) => 0.621371192 * kmph; + const levenshteinDistance = (string1, string2) => { + if (string1.length === 0) return string2.length; + if (string2.length === 0) return string1.length; + let matrix = Array(string2.length + 1) + .fill(0) + .map((x, i) => [i]); + matrix[0] = Array(string1.length + 1) + .fill(0) + .map((x, i) => i); + for (let i = 1; i <= string2.length; i++) { + for (let j = 1; j <= string1.length; j++) { + if (string2[i - 1] === string1[j - 1]) { + matrix[i][j] = matrix[i - 1][j - 1]; + } else { + matrix[i][j] = Math.min( + matrix[i - 1][j - 1] + 1, + matrix[i][j - 1] + 1, + matrix[i - 1][j] + 1 + ); + } + } + } + return matrix[string2.length][string1.length]; +}; + const mphToKmph = (mph) => 1.6093440006146922 * mph; + const pipeLog = data => console.log(data) || data; + const quickSort = ([n, ...nums], desc) => + isNaN(n) + ? [] + : [ + ...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc), + n, + ...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc) + ]; + const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi, repl); + const solveRPN = rpn => { + const OPERATORS = { + '*': (a, b) => a * b, + '+': (a, b) => a + b, + '-': (a, b) => a - b, + '/': (a, b) => a / b, + '**': (a, b) => a ** b + }; + const [stack, solve] = [ + [], + rpn + .replace(/\^/g, '**') + .split(/\s+/g) + .filter(el => !/\s+/.test(el) && el !== '') + ]; + solve.forEach(symbol => { + if (!isNaN(parseFloat(symbol)) && isFinite(symbol)) { + stack.push(symbol); + } else if (Object.keys(OPERATORS).includes(symbol)) { + const [a, b] = [stack.pop(), stack.pop()]; + stack.push(OPERATORS[symbol](parseFloat(b), parseFloat(a))); + } else { + throw `${symbol} is not a recognized symbol`; + } + }); + if (stack.length === 1) return stack.pop(); + else throw `${rpn} is not a proper RPN. Please check it and try again`; +}; + const speechSynthesis = message => { + const msg = new SpeechSynthesisUtterance(message); + msg.voice = window.speechSynthesis.getVoices()[0]; + window.speechSynthesis.speak(msg); +}; + const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0); -module.exports = {CSVToArray,CSVToJSON,JSONToFile,JSONtoCSV,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compactWhitespace,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,counter,createDirIfNotExists,createElement,createEventHub,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,deepMapKeys,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterFalsy,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,inRange,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNegativeZero,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,midpoint,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reduceSuccessive,reduceWhich,reducedFilter,reject,remove,removeNonASCII,renameKeys,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toHash,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toTitleCase,toggleClass,tomorrow,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith,JSONToDate,binarySearch,celsiusToFahrenheit,cleanObj,collatz,countVowels,factors,fahrenheitToCelsius,fibonacciCountUntilNum,fibonacciUntilNum,heronArea,howManyTimes,httpDelete,httpPut,isArmstrongNumber,isSimilar,kmphToMph,levenshteinDistance,mphToKmph,pipeLog,quickSort,removeVowels,solveRPN,speechSynthesis,squareSum} \ No newline at end of file +module.exports = {all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compactWhitespace,compose,composeRight,converge,copyToClipboard,countBy,counter,countOccurrences,createDirIfNotExists,createElement,createEventHub,CSVToArray,CSVToJSON,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,deepMapKeys,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterFalsy,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,formatDuration,forOwn,forOwnRight,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,inRange,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNegativeZero,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,JSONtoCSV,JSONToFile,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapNumRange,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,midpoint,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,once,onUserInputChange,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reducedFilter,reduceSuccessive,reduceWhich,reject,remove,removeNonASCII,renameKeys,reverseString,RGBToHex,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,times,timeTaken,toCamelCase,toCurrency,toDecimalMark,toggleClass,toHash,toKebabCase,tomorrow,toOrdinalSuffix,toSafeInteger,toSnakeCase,toTitleCase,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith,binarySearch,celsiusToFahrenheit,cleanObj,collatz,countVowels,factors,fahrenheitToCelsius,fibonacciCountUntilNum,fibonacciUntilNum,heronArea,howManyTimes,httpDelete,httpPut,isArmstrongNumber,isSimilar,JSONToDate,kmphToMph,levenshteinDistance,mphToKmph,pipeLog,quickSort,removeVowels,solveRPN,speechSynthesis,squareSum} \ No newline at end of file diff --git a/test/mapNumRange.test.js b/test/mapNumRange.test.js index 77ca11e8d..8bd1d1964 100644 --- a/test/mapNumRange.test.js +++ b/test/mapNumRange.test.js @@ -5,5 +5,5 @@ test('mapNumRange is a Function', () => { expect(mapNumRange).toBeInstanceOf(Function); }); test('Maps 5 to the range 0-100 from 0-10', () => { - expect(distance(5,0,10,0,100)).toEqual(50); + expect(mapNumRange(5,0,10,0,100)).toEqual(50); });