From 0dca4d0374c01f6b1d40bac0b1ddc766df278b26 Mon Sep 17 00:00:00 2001 From: 30secondsofcode <30secondsofcode@gmail.com> Date: Mon, 27 May 2019 15:43:01 +0000 Subject: [PATCH] Travis build: 1170 --- README.md | 8861 +++++++++++++++++++++-------------------- docs/browser.html | 2 +- docs/function.html | 1 + snippets/checkProp.md | 1 + test/_30s.js | 3054 +++++++------- 5 files changed, 5961 insertions(+), 5958 deletions(-) diff --git a/README.md b/README.md index 982b6671f..1a2e91391 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) [![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) [![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 @@ -511,23 +511,23 @@ _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)); +const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); ```
Examples ```js -const firstTwoMax = ary(Math.max, 2); -[[2, 6, 'a'], [8, 4, 6], [10]].map(x => firstTwoMax(...x)); // [6, 8, 10] -``` +const firstTwoMax = ary(Math.max, 2); +[[2, 6, 'a'], [8, 4, 6], [10]].map(x => firstTwoMax(...x)); // [6, 8, 10] +```
@@ -612,158 +612,158 @@ 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)); +const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); ```
Examples ```js -const minMax = over(Math.min, Math.max); -minMax(1, 2, 3, 4, 5); // [1,5] -``` +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))); +const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); ```
Examples ```js -const square = n => n * n; -const double = n => n * 2; -const fn = overArgs((x, y) => [x, y], [square, double]); -fn(9, 3); // [81, 6] -``` +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. - +### 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)); +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) -})(); -``` +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))); +const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); ```
Examples ```js -const add5 = x => x + 5; -const multiply = (x, y) => x * y; -const multiplyAndAdd5 = pipeFunctions(multiply, add5); -multiplyAndAdd5(5, 2); // 15 -``` +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) => - func(...args, (err, result) => (err ? reject(err) : resolve(result))) - ); +const promisify = func => (...args) => + new Promise((resolve, reject) => + func(...args, (err, result) => (err ? reject(err) : resolve(result))) + ); ```
Examples ```js -const delay = promisify((d, cb) => setTimeout(cb, d)); -delay(2000).then(() => console.log('Hi!')); // // Promise resolves after 2s -``` +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])); +const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); ```
Examples ```js -var rearged = rearg( - function(a, b, c) { - return [a, b, c]; - }, - [2, 0, 1] -); -rearged('b', 'c', 'a'); // ['a', 'b', 'c'] -``` +var rearged = rearg( + function(a, b, c) { + return [a, b, c]; + }, + [2, 0, 1] +); +rearged('b', 'c', 'a'); // ['a', 'b', 'c'] +```
@@ -791,22 +791,22 @@ 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); +const unary = fn => val => fn(val); ```
Examples ```js -['6', '8', '10'].map(unary(parseInt)); // [6, 8, 10] -``` +['6', '8', '10'].map(unary(parseInt)); // [6, 8, 10] +```
@@ -817,447 +817,447 @@ 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); +const all = (arr, fn = Boolean) => arr.every(fn); ```
Examples ```js -all([4, 2, 3], x => x > 1); // true -all([1, 2, 3]); // true -``` +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. -Elements in the array are compared using the strict comparison operator, which does not account for `NaN` self-inequality. - -```js -const allEqual = arr => arr.every(val => val === arr[0]); +### 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. +Elements in the array are compared using the strict comparison operator, which does not account for `NaN` self-inequality. + +```js +const allEqual = arr => arr.every(val => val === arr[0]); ```
Examples -```js -allEqual([1, 2, 3, 4, 5, 6]); // false -allEqual([1, 1, 1, 1]); // true -``` +```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); +const any = (arr, fn = Boolean) => arr.some(fn); ```
Examples ```js -any([0, 1, 2, 0], x => x >= 2); // true -any([0, 0, 1, 0]); // true -``` +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 => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter)) - .join('\n'); +const arrayToCSV = (arr, delimiter = ',') => + arr + .map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter)) + .join('\n'); ```
Examples ```js -arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"' -arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"' -arrayToCSV([['a', '"b" great'], ['c', 3.1415]]); // '"a","""b"" great"\n"c",3.1415' -``` +arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"' +arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"' +arrayToCSV([['a', '"b" great'], ['c', 3.1415]]); // '"a","""b"" great"\n"c",3.1415' +```

[⬆ 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), [[], []]); +const bifurcate = (arr, filter) => + arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); ```
Examples ```js -bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); // [ ['beep', 'boop', 'bar'], ['foo'] ] -``` +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), [[], []]); +const bifurcateBy = (arr, fn) => + arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); ```
Examples ```js -bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ] -``` +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) => - arr.slice(i * size, i * size + size) - ); +const chunk = (arr, size) => + Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => + arr.slice(i * size, i * size + size) + ); ```
Examples ```js -chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]] -``` +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); +const compact = arr => arr.filter(Boolean); ```
Examples ```js -compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); // [ 1, 2, 3, 'a', 's', 34 ] -``` +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); +const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); ```
Examples ```js -countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3 -``` +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))); +const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); ```
Examples ```js -deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5] -``` +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); - return a.filter(x => !s.has(x)); -}; +const difference = (a, b) => { + const s = new Set(b); + return a.filter(x => !s.has(x)); +}; ```
Examples ```js -difference([1, 2, 3], [1, 2, 4]); // [3] -``` +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.map()` to apply `fn` to each element in `a`, then `Array.prototype.filter()` - +### 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.map()` to apply `fn` to each element in `a`, then `Array.prototype.filter()` + ```js -const differenceBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.map(fn).filter(el => !s.has(el)); -}; +const differenceBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.map(fn).filter(el => !s.has(el)); +}; ```
Examples ```js -differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1] -differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [2] -``` +differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1] +differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.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); +const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); ```
Examples ```js -differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2] -``` +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 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 remove the specified number of elements from the left. + ```js -const drop = (arr, n = 1) => arr.slice(n); +const drop = (arr, n = 1) => arr.slice(n); ```
Examples ```js -drop([1, 2, 3]); // [2,3] -drop([1, 2, 3], 2); // [3] -drop([1, 2, 3], 42); // [] -``` +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 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 remove the specified number of elements from the right. + ```js -const dropRight = (arr, n = 1) => arr.slice(0, -n); +const dropRight = (arr, n = 1) => arr.slice(0, -n); ```
Examples ```js -dropRight([1, 2, 3]); // [1,2] -dropRight([1, 2, 3], 2); // [1] -dropRight([1, 2, 3], 42); // [] -``` +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); - return arr; -}; +const dropRightWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); + return arr; +}; ```
Examples ```js -dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2] -``` +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); - return arr; -}; +const dropWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); + return arr; +}; ```
Examples ```js -dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4] -``` +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); +const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); ```
Examples ```js -everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ] -``` +everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ] +```
@@ -1284,505 +1284,505 @@ 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)); +const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); ```
Examples ```js -filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5] -``` +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))); +const filterNonUniqueBy = (arr, fn) => + arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); ```
Examples ```js -filterNonUniqueBy( - [ - { id: 0, value: 'a' }, - { id: 1, value: 'b' }, - { id: 2, value: 'c' }, - { id: 1, value: 'd' }, - { id: 0, value: 'e' } - ], - (a, b) => a.id == b.id -); // [ { id: 2, value: 'c' } ] -``` +filterNonUniqueBy( + [ + { id: 0, value: 'a' }, + { id: 1, value: 'b' }, + { id: 2, value: 'c' }, + { id: 1, value: 'd' }, + { id: 0, value: 'e' } + ], + (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(); +const findLast = (arr, fn) => arr.filter(fn).pop(); ```
Examples ```js -findLast([1, 2, 3, 4], n => n % 2 === 1); // 3 -``` +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 - .map((val, i) => [i, val]) - .filter(([i, val]) => fn(val, i, arr)) - .pop()[0]; +const findLastIndex = (arr, fn) => + arr + .map((val, i) => [i, val]) + .filter(([i, val]) => fn(val, i, arr)) + .pop()[0]; ```
Examples ```js -findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3) -``` +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), []); +const flatten = (arr, depth = 1) => + arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); ```
Examples ```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] -``` +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 - .slice(0) - .reverse() - .forEach(callback); +const forEachRight = (arr, callback) => + arr + .slice(0) + .reverse() + .forEach(callback); ```
Examples ```js -forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1' -``` +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) => { - acc[val] = (acc[val] || []).concat(arr[i]); - return acc; - }, {}); +const groupBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { + acc[val] = (acc[val] || []).concat(arr[i]); + return acc; + }, {}); ```
Examples ```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']} -``` +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]; +const head = arr => arr[0]; ```
Examples ```js -head([1, 2, 3]); // 1 -``` +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), []); +const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); ```
Examples ```js -indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3] -indexOfAll([1, 2, 3], 4); // [] -``` +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); +const initial = arr => arr.slice(0, -1); ```
Examples ```js -initial([1, 2, 3]); // [1,2] -``` +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)); +const initialize2DArray = (w, h, val = null) => + Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); ```
Examples ```js -initialize2DArray(2, 2, 0); // [[0,0], [0,0]] -``` +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); +const initializeArrayWithRange = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); ```
Examples ```js -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] -``` +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( - (v, i, arr) => (arr.length - i - 1) * step + start - ); +const initializeArrayWithRangeRight = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( + (v, i, arr) => (arr.length - i - 1) * step + start + ); ```
Examples ```js -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] -``` +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); +const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); ```
Examples ```js -initializeArrayWithValues(5, 2); // [2, 2, 2, 2, 2] -``` +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 - ? val - : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); +const initializeNDArray = (val, ...args) => + args.length === 0 + ? val + : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); ```
Examples ```js -initializeNDArray(1, 3); // [1,1,1] -initializeNDArray(5, 2, 2, 2); // [[[5,5],[5,5]],[[5,5],[5,5]]] -``` +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); - return a.filter(x => s.has(x)); -}; +const intersection = (a, b) => { + const s = new Set(b); + return a.filter(x => s.has(x)); +}; ```
Examples ```js -intersection([1, 2, 3], [4, 3, 2]); // [2, 3] -``` +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)); - return a.filter(x => s.has(fn(x))); -}; +const intersectionBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => s.has(fn(x))); +}; ```
Examples ```js -intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1] -``` +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); +const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); ```
Examples ```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] -``` +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]); - for (let [i, val] of arr.entries()) { - direction = !direction ? -(arr[i - 1] - arr[i]) : direction; - if (i === arr.length - 1) return !direction ? 0 : direction; - else if ((val - arr[i + 1]) * direction > 0) return 0; - } -}; +const isSorted = arr => { + let direction = -(arr[0] - arr[1]); + for (let [i, val] of arr.entries()) { + direction = !direction ? -(arr[i - 1] - arr[i]) : direction; + if (i === arr.length - 1) return !direction ? 0 : direction; + else if ((val - arr[i + 1]) * direction > 0) return 0; + } +}; ```
Examples ```js -isSorted([0, 1, 2, 2]); // 1 -isSorted([4, 3, 2]); // -1 -isSorted([4, 3, 5]); // 0 -``` +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( - (acc, val, i) => - i === arr.length - 2 - ? acc + val + end - : i === arr.length - 1 - ? acc + val - : acc + val + separator, - '' - ); +const join = (arr, separator = ',', end = separator) => + arr.reduce( + (acc, val, i) => + i === arr.length - 2 + ? acc + val + end + : i === arr.length - 1 + ? acc + val + : acc + val + separator, + '' + ); ```
Examples ```js -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" -``` +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" +```
@@ -1822,49 +1822,49 @@ 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]; +const last = arr => arr[arr.length - 1]; ```
Examples ```js -last([1, 2, 3]); // 3 -``` +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' +```
@@ -1895,152 +1895,152 @@ 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); +const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); ```
Examples ```js -maxN([1, 2, 3]); // [3] -maxN([1, 2, 3], 2); // [3,2] -``` +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); +const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); ```
Examples ```js -minN([1, 2, 3]); // [1] -minN([1, 2, 3], 2); // [1,2] -``` +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); +const none = (arr, fn = Boolean) => !arr.some(fn); ```
Examples ```js -none([0, 1, 3, 0], x => x == 2); // true -none([0, 0, 0]); // true -``` +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]; +const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; ```
Examples ```js -nthElement(['a', 'b', 'c'], 1); // 'b' -nthElement(['a', 'b', 'b'], -3); // 'a' -``` +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)]; +const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; ```
Examples ```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] -``` +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( - (acc, val, i, arr) => { - acc[fn(val, i, arr) ? 0 : 1].push(val); - return acc; - }, - [[], []] - ); +const partition = (arr, fn) => + arr.reduce( + (acc, val, i, arr) => { + acc[fn(val, i, arr) ? 0 : 1].push(val); + return acc; + }, + [[], []] + ); ```
Examples ```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 }]] -``` +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 }]] +```
@@ -2081,31 +2081,31 @@ 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; - let pulled = arr.filter((v, i) => !argState.includes(v)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); -}; +const pull = (arr, ...args) => { + let argState = Array.isArray(args[0]) ? args[0] : args; + let pulled = arr.filter((v, i) => !argState.includes(v)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); +}; ```
Examples ```js -let myArray = ['a', 'b', 'c', 'a', 'b', 'c']; -pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ] -``` +let myArray = ['a', 'b', 'c', 'a', 'b', 'c']; +pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ] +```
@@ -2207,385 +2207,385 @@ 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 => - keys.reduce((acc, key) => { - acc[key] = el[key]; - return acc; - }, {}) - ); +const reducedFilter = (data, keys, fn) => + data.filter(fn).map(el => + keys.reduce((acc, key) => { + acc[key] = el[key]; + return acc; + }, {}) + ); ```
Examples ```js -const data = [ - { - id: 1, - name: 'john', - age: 24 - }, - { - id: 2, - name: 'mike', - age: 50 - } -]; - -reducedFilter(data, ['id', 'name'], item => item.age > 24); // [{ id: 2, name: 'mike'}] -``` +const data = [ + { + id: 1, + name: 'john', + age: 24 + }, + { + id: 2, + name: 'mike', + age: 50 + } +]; + +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]); +const reduceSuccessive = (arr, fn, acc) => + arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); ```
Examples ```js -reduceSuccessive([1, 2, 3, 4, 5, 6], (acc, val) => acc + val, 0); // [0, 1, 3, 6, 10, 15, 21] -``` +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)); +const reduceWhich = (arr, comparator = (a, b) => a - b) => + arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); ```
Examples ```js -reduceWhich([1, 3, 2]); // 1 -reduceWhich([1, 3, 2], (a, b) => b - a); // 3 -reduceWhich( - [{ name: 'Tom', age: 12 }, { name: 'Jack', age: 18 }, { name: 'Lucy', age: 9 }], - (a, b) => a.age - b.age -); // {name: "Lucy", age: 9} -``` +reduceWhich([1, 3, 2]); // 1 +reduceWhich([1, 3, 2], (a, b) => b - a); // 3 +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)); +const reject = (pred, array) => array.filter((...args) => !pred(...args)); ```
Examples ```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'] -``` +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 - -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`). - +### 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); - }, []) - : []; +const remove = (arr, func) => + Array.isArray(arr) + ? arr.filter(func).reduce((acc, val) => { + arr.splice(arr.indexOf(val), 1); + return acc.concat(val); + }, []) + : []; ```
Examples ```js -remove([1, 2, 3, 4], n => n % 2 === 0); // [2, 4] -``` +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. - +### 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)]; +const sample = arr => arr[Math.floor(Math.random() * arr.length)]; ```
Examples ```js -sample([3, 7, 9, 11]); // 9 -``` +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; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr.slice(0, n); -}; +const sampleSize = ([...arr], n = 1) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr.slice(0, n); +}; ```
Examples ```js -sampleSize([1, 2, 3], 2); // [3,1] -sampleSize([1, 2, 3], 4); // [2,3,1] -``` +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; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr; -}; +const shuffle = ([...arr]) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr; +}; ```
Examples ```js -const foo = [1, 2, 3]; -shuffle(foo); // [2, 3, 1], foo = [1, 2, 3] -``` +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)); +const similarity = (arr, values) => arr.filter(v => values.includes(v)); ```
Examples ```js -similarity([1, 2, 3], [1, 2, 4]); // [1, 2] -``` +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]; - const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); - return index === -1 ? arr.length : index; -}; +const sortedIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); + return index === -1 ? arr.length : index; +}; ```
Examples ```js -sortedIndex([5, 3, 2, 1], 4); // 1 -sortedIndex([30, 50], 40); // 1 -``` +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]); - const val = fn(n); - const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); - return index === -1 ? arr.length : index; -}; +const sortedIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); + return index === -1 ? arr.length : index; +}; ```
Examples ```js -sortedIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 0 -``` +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]; - const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); - return index === -1 ? 0 : arr.length - index; -}; +const sortedLastIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); + return index === -1 ? 0 : arr.length - index; +}; ```
Examples ```js -sortedLastIndex([10, 20, 30, 30, 40], 30); // 4 -``` +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]); - const val = fn(n); - const index = arr - .map(fn) - .reverse() - .findIndex(el => (isDescending ? val <= el : val >= el)); - return index === -1 ? 0 : arr.length - index; -}; +const sortedLastIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr + .map(fn) + .reverse() + .findIndex(el => (isDescending ? val <= el : val >= el)); + return index === -1 ? 0 : arr.length - index; +}; ```
Examples ```js -sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1 -``` +sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1 +```
@@ -2620,444 +2620,444 @@ 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), - sB = new Set(b); - return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; -}; +const symmetricDifference = (a, b) => { + const sA = new Set(a), + sB = new Set(b); + return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; +}; ```
Examples ```js -symmetricDifference([1, 2, 3], [1, 2, 4]); // [3, 4] -symmetricDifference([1, 2, 2], [1, 3, 1]); // [2, 2, 3] -``` +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))), - sB = new Set(b.map(v => fn(v))); - return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; -}; +const symmetricDifferenceBy = (a, b, fn) => { + const sA = new Set(a.map(v => fn(v))), + sB = new Set(b.map(v => fn(v))); + return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; +}; ```
Examples ```js -symmetricDifferenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [ 1.2, 3.4 ] -``` +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), - ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) -]; +const symmetricDifferenceWith = (arr, val, comp) => [ + ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), + ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) +]; ```
Examples ```js -symmetricDifferenceWith( - [1, 1.2, 1.5, 3, 0], - [1.9, 3, 0, 3.9], - (a, b) => Math.round(a) === Math.round(b) -); // [1, 1.2, 3.9] -``` +symmetricDifferenceWith( + [1, 1.2, 1.5, 3, 0], + [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); +const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); ```
Examples ```js -tail([1, 2, 3]); // [2,3] -tail([1]); // [1] -``` +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); +const take = (arr, n = 1) => arr.slice(0, n); ```
Examples ```js -take([1, 2, 3], 5); // [1, 2, 3] -take([1, 2, 3], 0); // [] -``` +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); +const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); ```
Examples ```js -takeRight([1, 2, 3], 2); // [ 2, 3 ] -takeRight([1, 2, 3]); // [3] -``` +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); - return arr; -}; +const takeWhile = (arr, func) => { + for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); + return arr; +}; ```
Examples ```js -takeWhile([1, 2, 3, 4], n => n >= 3); // [1, 2] -``` +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])); +const union = (a, b) => Array.from(new Set([...a, ...b])); ```
Examples ```js -union([1, 2, 3], [4, 3, 2]); // [1,2,3,4] -``` +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)])); +const unionWith = (a, b, comp) => + Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); ```
Examples ```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] -``` +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)]; +const uniqueElements = arr => [...new Set(arr)]; ```
Examples ```js -uniqueElements([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5] -``` +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 occurrence 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 occurrence 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) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); +const uniqueElementsBy = (arr, fn) => + arr.reduce((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); ```
Examples ```js -uniqueElementsBy( - [ - { id: 0, value: 'a' }, - { id: 1, value: 'b' }, - { id: 2, value: 'c' }, - { id: 1, value: 'd' }, - { id: 0, value: 'e' } - ], - (a, b) => a.id == b.id -); // [ { id: 0, value: 'a' }, { id: 1, value: 'b' }, { id: 2, value: 'c' } ] -``` +uniqueElementsBy( + [ + { id: 0, value: 'a' }, + { id: 1, value: 'b' }, + { id: 2, value: 'c' }, + { id: 1, value: 'd' }, + { id: 0, value: 'e' } + ], + (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 occurrence 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 occurrence 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) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); +const uniqueElementsByRight = (arr, fn) => + arr.reduceRight((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); ```
Examples ```js -uniqueElementsByRight( - [ - { id: 0, value: 'a' }, - { id: 1, value: 'b' }, - { id: 2, value: 'c' }, - { id: 1, value: 'd' }, - { id: 0, value: 'e' } - ], - (a, b) => a.id == b.id -); // [ { id: 0, value: 'e' }, { id: 1, value: 'd' }, { id: 2, value: 'c' } ] -``` +uniqueElementsByRight( + [ + { id: 0, value: 'a' }, + { id: 1, value: 'b' }, + { id: 2, value: 'c' }, + { id: 1, value: 'd' }, + { id: 0, value: 'e' } + ], + (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))]) -]; +const uniqueSymmetricDifference = (a, b) => [ + ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) +]; ```
Examples ```js -uniqueSymmetricDifference([1, 2, 3], [1, 2, 4]); // [3, 4] -uniqueSymmetricDifference([1, 2, 2], [1, 3, 1]); // [2, 3] -``` +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]] +```
@@ -3094,97 +3094,97 @@ 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)); +const without = (arr, ...args) => arr.filter(v => !args.includes(v)); ```
Examples ```js -without([2, 1, 2, 3], 1, 2); // [3] -``` +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])), []); +const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); ```
Examples ```js -xProd([1, 2], ['a', 'b']); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']] -``` +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)); - return Array.from({ length: maxLength }).map((_, i) => { - return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); - }); -}; +const zip = (...arrays) => { + const maxLength = Math.max(...arrays.map(x => x.length)); + return Array.from({ length: maxLength }).map((_, i) => { + return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); + }); +}; ```
Examples ```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]] -``` +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), {}); +const zipObject = (props, values) => + props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); ```
Examples ```js -zipObject(['a', 'b', 'c'], [1, 2]); // {a: 1, b: 2, c: undefined} -zipObject(['a', 'b'], [1, 2, 3]); // {a: 1, b: 2} -``` +zipObject(['a', 'b', 'c'], [1, 2]); // {a: 1, b: 2, c: undefined} +zipObject(['a', 'b'], [1, 2, 3]); // {a: 1, b: 2} +```
@@ -3232,49 +3232,49 @@ 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 => ( - (el = document.querySelector('#' + listID)), - (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) - ))(); +const arrayToHtmlList = (arr, listID) => + (el => ( + (el = document.querySelector('#' + listID)), + (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) + ))(); ```
    Examples ```js -arrayToHtmlList(['item 1', 'item 2'], 'myListID'); -``` +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 >= - (document.documentElement.scrollHeight || document.documentElement.clientHeight); +const bottomVisible = () => + document.documentElement.clientHeight + window.scrollY >= + (document.documentElement.scrollHeight || document.documentElement.clientHeight); ```
    Examples ```js -bottomVisible(); // true -``` +bottomVisible(); // true +```
    @@ -3359,34 +3359,34 @@ 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'); - el.innerHTML = str; - return el.firstElementChild; -}; +const createElement = str => { + const el = document.createElement('div'); + el.innerHTML = str; + return el.firstElementChild; +}; ```
    Examples ```js -const el = createElement( - `
    -

    Hello!

    -
    ` -); -console.log(el.className); // 'container' -``` +const el = createElement( + `
    +

    Hello!

    +
    ` +); +console.log(el.className); // 'container' +```
    @@ -3445,68 +3445,68 @@ 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; +const currentURL = () => window.location.href; ```
    Examples ```js -currentURL(); // 'https://google.com' -``` +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 whether 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) - ? 'Mobile' - : 'Desktop'; +const detectDeviceType = () => + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + ? 'Mobile' + : 'Desktop'; ```
    Examples ```js -detectDeviceType(); // "Mobile" or "Desktop" -``` +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); +const elementContains = (parent, child) => parent !== child && parent.contains(child); ```
    Examples ```js -elementContains(document.querySelector('head'), document.querySelector('title')); // true -elementContains(document.querySelector('body'), document.querySelector('body')); // false -``` +elementContains(document.querySelector('head'), document.querySelector('title')); // true +elementContains(document.querySelector('body'), document.querySelector('body')); // false +```
    @@ -3545,122 +3545,122 @@ elementIsVisibleInViewport(el, true); // true - (partially visible)
    [⬆ Back to top](#contents) -### formToObject - -Encode a set of form elements as an `object`. - -Use the `FormData` constructor to convert the HTML `form` to `FormData`, `Array.from()` to convert to an array. -Collect the object from the array, using `Array.prototype.reduce()`. - +### formToObject + +Encode a set of form elements as an `object`. + +Use the `FormData` constructor to convert the HTML `form` to `FormData`, `Array.from()` to convert to an array. +Collect the object from the array, using `Array.prototype.reduce()`. + ```js -const formToObject = form => - Array.from(new FormData(form)).reduce( - (acc, [key, value]) => ({ - ...acc, - [key]: value - }), - {} - ); +const formToObject = form => + Array.from(new FormData(form)).reduce( + (acc, [key, value]) => ({ + ...acc, + [key]: value + }), + {} + ); ```
    Examples ```js -formToObject(document.querySelector('#form')); // { email: 'test@email.com', name: 'Test Name' } -``` +formToObject(document.querySelector('#form')); // { email: 'test@email.com', name: 'Test Name' } +```

    [⬆ 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, - y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop -}); +const getScrollPosition = (el = window) => ({ + x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, + y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop +}); ```
    Examples ```js -getScrollPosition(); // {x: 0, y: 200} -``` +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]; +const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; ```
    Examples ```js -getStyle(document.querySelector('p'), 'font-size'); // '16px' -``` +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); +const hasClass = (el, className) => el.classList.contains(className); ```
    Examples ```js -hasClass(document.querySelector('p.special'), 'special'); // true -``` +hasClass(document.querySelector('p.special'), 'special'); // true +```
    @@ -3694,129 +3694,129 @@ 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]); -}; +const httpsRedirect = () => { + if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); +}; ```
    Examples ```js -httpsRedirect(); // If you are on http://mydomain.com, you are redirected to https://mydomain.com -``` +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); +const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); ```
    Examples ```js -insertAfter(document.getElementById('myId'), '

    after

    '); //
    ...

    after

    -``` +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); +const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); ```
    Examples ```js -insertBefore(document.getElementById('myId'), '

    before

    '); //

    before

    ...
    -``` +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; +const isBrowserTabFocused = () => !document.hidden; ```
    Examples ```js -isBrowserTabFocused(); // true -``` +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]; +const nodeListToArray = nodeList => [...nodeList]; ```
    Examples ```js -nodeListToArray(document.childNodes); // [ , html ] -``` +nodeListToArray(document.childNodes); // [ , html ] +```
    @@ -3863,55 +3863,55 @@ 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); +const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); ```
    Examples ```js -const fn = () => console.log('!'); -document.body.addEventListener('click', fn); -off(document.body, 'click', fn); // no longer logs '!' upon clicking on the page -``` +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); - el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); - if (opts.target) return delegatorFn; -}; +const on = (el, evt, fn, opts = {}) => { + const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); + el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); + if (opts.target) return delegatorFn; +}; ```
    Examples ```js -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 -``` +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 +```
    @@ -3955,100 +3955,100 @@ 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); - const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; - const i = prefixes.findIndex( - prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' - ); - return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; -}; +const prefix = prop => { + const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); + const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; + const i = prefixes.findIndex( + prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' + ); + return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; +}; ```
    Examples ```js -prefix('appearance'); // 'appearance' on a supported browser, otherwise 'webkitAppearance', 'mozAppearance', 'msAppearance' or 'oAppearance' -``` +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, - raf; - const stop = () => { - running = false; - cancelAnimationFrame(raf); - }; - const start = () => { - running = true; - run(); - }; - const run = () => { - raf = requestAnimationFrame(() => { - callback(); - if (running) run(); - }); - }; - if (autoStart) start(); - return { start, stop }; -}; +const recordAnimationFrames = (callback, autoStart = true) => { + let running = true, + raf; + const stop = () => { + running = false; + cancelAnimationFrame(raf); + }; + const start = () => { + running = true; + run(); + }; + const run = () => { + raf = requestAnimationFrame(() => { + callback(); + if (running) run(); + }); + }; + if (autoStart) start(); + return { start, stop }; +}; ```
    Examples ```js -const cb = () => console.log('Animation frame fired'); -const recorder = recordAnimationFrames(cb); // logs 'Animation frame fired' on each animation frame -recorder.stop(); // stops logging -recorder.start(); // starts again -const recorder2 = recordAnimationFrames(cb, false); // `start` needs to be explicitly called to begin recording frames -``` +const cb = () => console.log('Animation frame fired'); +const recorder = recordAnimationFrames(cb); // logs 'Animation frame fired' on each animation frame +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); +const redirect = (url, asLink = true) => + asLink ? (window.location.href = url) : window.location.replace(url); ```
    Examples ```js -redirect('https://google.com'); -``` +redirect('https://google.com'); +```
    @@ -4106,191 +4106,191 @@ 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; - if (c > 0) { - window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c / 8); - } -}; +const scrollToTop = () => { + const c = document.documentElement.scrollTop || document.body.scrollTop; + if (c > 0) { + window.requestAnimationFrame(scrollToTop); + window.scrollTo(0, c - c / 8); + } +}; ```
    Examples ```js -scrollToTop(); -``` +scrollToTop(); +```

    [⬆ Back to top](#contents) -### serializeForm - -Encode a set of form elements as a query string. - -Use the `FormData` constructor to convert the HTML `form` to `FormData`, `Array.from()` to convert to an array, passing a map function as the second argument. -Use `Array.prototype.map()` and `window.encodeURIComponent()` to encode each field's value. -Use `Array.prototype.join()` with appropriate argumens to produce an appropriate query string. - +### serializeForm + +Encode a set of form elements as a query string. + +Use the `FormData` constructor to convert the HTML `form` to `FormData`, `Array.from()` to convert to an array, passing a map function as the second argument. +Use `Array.prototype.map()` and `window.encodeURIComponent()` to encode each field's value. +Use `Array.prototype.join()` with appropriate argumens to produce an appropriate query string. + ```js -const serializeForm = form => - Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&'); +const serializeForm = form => + Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&'); ```
    Examples ```js -serializeForm(document.querySelector('#form')); // email=test%40email.com&name=Test%20Name -``` +serializeForm(document.querySelector('#form')); // email=test%40email.com&name=Test%20Name +```

    [⬆ 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); +const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); ```
    Examples ```js -setStyle(document.querySelector('p'), 'font-size', '20px'); // The first

    element on the page will have a font-size of 20px -``` +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 = '')); +const show = (...el) => [...el].forEach(e => (e.style.display = '')); ```
    Examples ```js -show(...document.querySelectorAll('img')); // Shows all elements on the page -``` +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({ - behavior: 'smooth' - }); +const smoothScroll = element => + document.querySelector(element).scrollIntoView({ + behavior: 'smooth' + }); ```
    Examples ```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 -``` +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); +const toggleClass = (el, className) => el.classList.toggle(className); ```
    Examples ```js -toggleClass(document.querySelector('p.special'), 'special'); // The paragraph will not have the 'special' class anymore -``` +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 => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) - ); +const UUIDGeneratorBrowser = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) + ); ```
    Examples ```js -UUIDGeneratorBrowser(); // '7982fcfe-5721-4632-bede-6000885be57d' -``` +UUIDGeneratorBrowser(); // '7982fcfe-5721-4632-bede-6000885be57d' +```
    @@ -4301,279 +4301,279 @@ 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; - const time = { - day: Math.floor(ms / 86400000), - hour: Math.floor(ms / 3600000) % 24, - minute: Math.floor(ms / 60000) % 60, - second: Math.floor(ms / 1000) % 60, - millisecond: Math.floor(ms) % 1000 - }; - return Object.entries(time) - .filter(val => val[1] !== 0) - .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) - .join(', '); -}; +const formatDuration = ms => { + if (ms < 0) ms = -ms; + const time = { + day: Math.floor(ms / 86400000), + hour: Math.floor(ms / 3600000) % 24, + minute: Math.floor(ms / 60000) % 60, + second: Math.floor(ms / 1000) % 60, + millisecond: Math.floor(ms) % 1000 + }; + return Object.entries(time) + .filter(val => val[1] !== 0) + .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) + .join(', '); +}; ```
    Examples ```js -formatDuration(1001); // '1 second, 1 millisecond' -formatDuration(34325055574); // '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds' -``` +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); +const getDaysDiffBetweenDates = (dateInitial, dateFinal) => + (dateFinal - dateInitial) / (1000 * 3600 * 24); ```
    Examples ```js -getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9 -``` +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-19 (if current date is 2018-10-18) -``` +tomorrow(); // 2018-10-19 (if current date is 2018-10-18) +```
    @@ -4584,433 +4584,434 @@ tomorrow(); // 2018-10-19 (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 { - return fn(...args); - } catch (e) { - return e instanceof Error ? e : new Error(e); - } -}; +const attempt = (fn, ...args) => { + try { + return fn(...args); + } catch (e) { + return e instanceof Error ? e : new Error(e); + } +}; ```
    Examples ```js -var elements = attempt(function(selector) { - return document.querySelectorAll(selector); -}, '>_>'); -if (elements instanceof Error) elements = []; // elements = [] -``` +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]); +const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); ```
    Examples ```js -function greet(greeting, punctuation) { - return greeting + ' ' + this.user + punctuation; -} -const freddy = { user: 'fred' }; -const freddyBound = bind(greet, freddy); -console.log(freddyBound('hi', '!')); // 'hi fred!' -``` +function greet(greeting, punctuation) { + return greeting + ' ' + this.user + 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]); +const bindKey = (context, fn, ...boundArgs) => (...args) => + context[fn].apply(context, [...boundArgs, ...args]); ```
    Examples ```js -const freddy = { - user: 'fred', - greet: function(greeting, punctuation) { - return greeting + ' ' + this.user + punctuation; - } -}; -const freddyBound = bindKey(freddy, 'greet'); -console.log(freddyBound('hi', '!')); // 'hi fred!' -``` +const freddy = { + user: 'fred', + greet: function(greeting, punctuation) { + return greeting + ' ' + this.user + punctuation; + } +}; +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) -### checkProp - -Given a `predicate` function and a `prop` string, this curried function will then take an `object` to inspect by calling the property and passing it to the predicate. - -Summon `prop` on `obj`, pass it to a provided `predicate` function and return a masked boolean. - +### checkProp + +Given a `predicate` function and a `prop` string, this curried function will then take an `object` to inspect by calling the property and passing it to the predicate. + +Summon `prop` on `obj`, pass it to a provided `predicate` function and return a masked boolean. + ```js -const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]); +const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]); ```
    Examples ```js - - - - - - - - - -const lengthIs4 = checkProp(l => l === 4, 'length'); -lengthIs4([]); // false -lengthIs4([1,2,3,4]); // true -lengthIs4(new Set([1,2,3,4])); // false (Set uses Size, not length) - -const session = { user: {} }; -const validUserSession = checkProps(u => u.active && !u.disabled, 'user'); - -validUserSession(session); // false - -session.user.active = true; -validUserSession(session); // true - -const noLength(l => l === undefined, 'length'); -noLength([]); // false -noLength({}); // true -noLength(new Set()); // true -``` + + + + + + + + + + +const lengthIs4 = checkProp(l => l === 4, 'length'); +lengthIs4([]); // false +lengthIs4([1,2,3,4]); // true +lengthIs4(new Set([1,2,3,4])); // false (Set uses Size, not length) + +const session = { user: {} }; +const validUserSession = checkProps(u => u.active && !u.disabled, 'user'); + +validUserSession(session); // false + +session.user.active = true; +validUserSession(session); // true + +const noLength(l => l === undefined, 'length'); +noLength([]); // false +noLength({}); // true +noLength(new Set()); // true +```

    [⬆ 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))); +const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); ```
    Examples ```js -const add = (x, y) => x + y; -const square = x => x * x; -const addAndSquare = composeRight(add, square); -addAndSquare(1, 2); // 9 -``` +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))); +const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); ```
    Examples ```js -const average = converge((a, b) => a / b, [ - arr => arr.reduce((a, v) => a + v, 0), - arr => arr.length -]); -average([1, 2, 3, 4, 5, 6, 7]); // 4 -``` +const average = converge((a, b) => a / b, [ + arr => arr.reduce((a, v) => a + v, 0), + 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); +const curry = (fn, arity = fn.length, ...args) => + arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); ```
    Examples ```js -curry(Math.pow)(2)(10); // 1024 -curry(Math.min, 3)(10)(50)(2); // 2 -``` +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; - return function(...args) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -}; +const debounce = (fn, ms = 0) => { + let timeoutId; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; ```
    Examples ```js -window.addEventListener( - 'resize', - debounce(() => { - console.log(window.innerWidth); - console.log(window.innerHeight); - }, 250) -); // Will log the window dimensions at most every 250ms -``` +window.addEventListener( + 'resize', + debounce(() => { + console.log(window.innerWidth); + 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); +const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); ```
    Examples ```js -delay( - function(text) { - console.log(text); - }, - 1000, - 'later' -); // Logs 'later' after one second. -``` +delay( + function(text) { + console.log(text); + }, + 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); +const functionName = fn => (console.debug(fn.name), fn); ```
    Examples ```js -functionName(Math.max); // max (logged in debug channel of console) -``` +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 +```
    @@ -5050,147 +5051,147 @@ 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); +const negate = func => (...args) => !func(...args); ```
    Examples ```js -[1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ] -``` +[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; - return function(...args) { - if (called) return; - called = true; - return fn.apply(this, args); - }; -}; +const once = fn => { + let called = false; + return function(...args) { + if (called) return; + called = true; + return fn.apply(this, args); + }; +}; ```
    Examples ```js -const startApp = function(event) { - console.log(this, event); // document.body, MouseEvent -}; -document.body.addEventListener('click', once(startApp)); // only runs `startApp` once upon click -``` +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); +const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); ```
    Examples ```js -const greet = (greeting, name) => greeting + ' ' + name + '!'; -const greetHello = partial(greet, 'Hello'); -greetHello('John'); // 'Hello John!' -``` +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); +const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); ```
    Examples ```js -const greet = (greeting, name) => greeting + ' ' + name + '!'; -const greetJohn = partialRight(greet, 'John'); -greetJohn('Hello'); // 'Hello John!' -``` +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()); +const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); ```
    Examples ```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 -``` +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)); +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); ```
    Examples ```js -async function sleepyWork() { - console.log("I'm going to sleep for 1 second."); - await sleep(1000); - console.log('I woke up after 1 second.'); -} -``` +async function sleepyWork() { + console.log("I'm going to sleep for 1 second."); + await sleep(1000); + console.log('I woke up after 1 second.'); +} +```
    @@ -5245,110 +5246,110 @@ 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; - while (fn.call(context, i) !== false && ++i < n) {} -}; +const times = (n, fn, context = undefined) => { + let i = 0; + while (fn.call(context, i) !== false && ++i < n) {} +}; ```
    Examples ```js -var output = ''; -times(5, i => (output += i)); -console.log(output); // 01234 -``` +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); - if (n > args.length) throw new RangeError('Arguments too few!'); - return next(fn)(args.slice(0, n)); -}; +const uncurry = (fn, n = 1) => (...args) => { + const next = acc => args => args.reduce((x, y) => x(y), acc); + if (n > args.length) throw new RangeError('Arguments too few!'); + return next(fn)(args.slice(0, n)); +}; ```
    Examples ```js -const add = x => y => z => x + y + z; -const uncurriedAdd = uncurry(add, 3); -uncurriedAdd(1, 2, 3); // 6 -``` +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 = [], - val = [null, seed]; - while ((val = fn(val[1]))) result.push(val[0]); - return result; -}; +const unfold = (fn, seed) => { + let result = [], + val = [null, seed]; + while ((val = fn(val[1]))) result.push(val[0]); + return result; +}; ```
    Examples ```js -var f = n => (n > 50 ? false : [-n, n + 10]); -unfold(f, 10); // [-10, -20, -30, -40, -50] -``` +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); +const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); ```
    Examples ```js -const doubleEvenNumbers = when(x => x % 2 === 0, x => x * 2); -doubleEvenNumbers(2); // 4 -doubleEvenNumbers(1); // 1 -``` +const doubleEvenNumbers = when(x => x % 2 === 0, x => x * 2); +doubleEvenNumbers(2); // 4 +doubleEvenNumbers(1); // 1 +```
    @@ -5359,190 +5360,190 @@ 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; +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; ```
    Examples ```js -approximatelyEqual(Math.PI / 2.0, 1.5708); // true -``` +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; +const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; ```
    Examples ```js -average(...[1, 2, 3]); // 2 -average(1, 2, 3); // 2 -``` +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) / - arr.length; +const averageBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / + arr.length; ```
    Examples ```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 -``` +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; - if (k < 0 || k > n) return 0; - if (k === 0 || k === n) return 1; - if (k === 1 || k === n - 1) return n; - if (n - k < k) k = n - k; - let res = n; - for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; - return Math.round(res); -}; +const binomialCoefficient = (n, k) => { + if (Number.isNaN(n) || Number.isNaN(k)) return NaN; + if (k < 0 || k > n) return 0; + if (k === 0 || k === n) return 1; + if (k === 1 || k === n - 1) return n; + if (n - k < k) k = n - k; + let res = n; + for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; + return Math.round(res); +}; ```
    Examples ```js -binomialCoefficient(8, 2); // 28 -``` +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)); +const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); ```
    Examples ```js -clampNumber(2, 3, 5); // 3 -clampNumber(1, -1, -5); // -1 -``` +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)); +const digitize = n => [...`${n}`].map(i => parseInt(i)); ```
    Examples ```js -digitize(123); // [1, 2, 3] -``` +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); +const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); ```
    Examples ```js -distance(1, 1, 2, 3); // 2.23606797749979 -``` +distance(1, 1, 2, 3); // 2.23606797749979 +```
    @@ -5598,282 +5599,282 @@ 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. - +### 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); +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 -``` +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( - (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), - [] - ); +const fibonacci = n => + Array.from({ length: n }).reduce( + (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), + [] + ); ```
    Examples ```js -fibonacci(6); // [0, 1, 1, 2, 3, 5] -``` +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)); - return [...arr].reduce((a, b) => _gcd(a, b)); -}; +const gcd = (...arr) => { + const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); + return [...arr].reduce((a, b) => _gcd(a, b)); +}; ```
    Examples ```js -gcd(8, 36); // 4 -gcd(...[12, 8, 32]); // 4 -``` +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( - (v, i) => start * step ** i - ); +const geometricProgression = (end, start = 1, step = 2) => + Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( + (v, i) => start * step ** i + ); ```
    Examples ```js -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] -``` +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; +const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; ```
    Examples ```js -hammingDistance(2, 3); // 1 -``` +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]; - return end == null ? n >= 0 && n < start : n >= start && n < end; -}; +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; +}; ```
    Examples ```js -inRange(3, 2, 5); // true -inRange(3, 4); // true -inRange(2, 3, 5); // false -inRange(3, 2); // false -``` +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; +const isDivisible = (dividend, divisor) => dividend % divisor === 0; ```
    Examples ```js -isDivisible(6, 3); // true -``` +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; +const isEven = num => num % 2 === 0; ```
    Examples ```js -isEven(3); // false -``` +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)); - for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; - return num >= 2; -}; +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; +}; ```
    Examples ```js -isPrime(11); // true -``` +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 +```
    @@ -5915,477 +5916,477 @@ luhnCheck(123456789); // false
    [⬆ Back to top](#contents) -### mapNumRange - -Maps a number from one range to another range. - -Returns `num` mapped between `outMin`-`outMax` from `inMin`-`inMax`. - +### 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; +const mapNumRange = (num, inMin, inMax, outMin, outMax) => + ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin; ```
    Examples ```js -mapNumRange(5, 0, 10, 0, 100); // 50 -``` +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. - +### 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])); +const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); ```
    Examples ```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 -``` +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), - nums = [...arr].sort((a, b) => a - b); - return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; -}; +const median = arr => { + const mid = Math.floor(arr.length / 2), + nums = [...arr].sort((a, b) => a - b); + return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; +}; ```
    Examples ```js -median([5, 6, 50, 1, -5]); // 5 -``` +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 minimum 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 minimum value. + ```js -const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); +const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); ```
    Examples ```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 -``` +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))), [[]]); +const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); ```
    Examples ```js -powerset([1, 2]); // [[], [1], [2], [2, 1]] -``` +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), - sqroot = Math.floor(Math.sqrt(num)), - numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); - numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); - return arr; -}; +const primes = num => { + let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), + sqroot = Math.floor(Math.sqrt(num)), + numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); + numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); + return arr; +}; ```
    Examples ```js -primes(10); // [2,3,5,7] -``` +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); +const randomIntArrayInRange = (min, max, n = 1) => + Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); ```
    Examples ```js -randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ] -``` +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; +const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; ```
    Examples ```js -randomIntegerInRange(0, 5); // 2 -``` +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; +const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; ```
    Examples ```js -randomNumberInRange(2, 10); // 6.0211363285087005 -``` +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}`); +const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); ```
    Examples ```js -round(1.005, 2); // 1.01 -``` +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(''); - return arr.reduce( - (hashCode, currentVal) => - (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), - 0 - ); -}; +const sdbm = str => { + let arr = str.split(''); + return arr.reduce( + (hashCode, currentVal) => + (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), + 0 + ); +}; ```
    Examples ```js -sdbm('name'); // -3521204949 -``` +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; - return Math.sqrt( - arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / - (arr.length - (usePopulation ? 0 : 1)) - ); -}; +const standardDeviation = (arr, usePopulation = false) => { + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + return Math.sqrt( + arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / + (arr.length - (usePopulation ? 0 : 1)) + ); +}; ```
    Examples ```js -standardDeviation([10, 2, 38, 23, 38, 23, 21]); // 13.284434142114991 (sample) -standardDeviation([10, 2, 38, 23, 38, 23, 21], true); // 12.29899614287479 (population) -``` +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); +const sumBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); ```
    Examples ```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 -``` +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)); +const toSafeInteger = num => + Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); ```
    Examples ```js -toSafeInteger('3.2'); // 3 -toSafeInteger(Infinity); // 9007199254740991 -``` +toSafeInteger('3.2'); // 3 +toSafeInteger(Infinity); // 9007199254740991 +```

    [⬆ Back to top](#contents) -### vectorDistance - -Returns the distance between two vectors. - -Use `Array.prototype.reduce()`, `Math.pow()` and `Math.sqrt()` to calculate the Euclidean distance between two vectors. - +### vectorDistance + +Returns the distance between two vectors. + +Use `Array.prototype.reduce()`, `Math.pow()` and `Math.sqrt()` to calculate the Euclidean distance between two vectors. + ```js -const vectorDistance = (...coords) => { - let pointLength = Math.trunc(coords.length / 2); - let sum = coords - .slice(0, pointLength) - .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0); - return Math.sqrt(sum); -}; +const vectorDistance = (...coords) => { + let pointLength = Math.trunc(coords.length / 2); + let sum = coords + .slice(0, pointLength) + .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0); + return Math.sqrt(sum); +}; ```
    Examples ```js -vectorDistance(10, 0, 5, 20, 0, 10); // 11.180339887498949 -``` +vectorDistance(10, 0, 5, 20, 0, 10); // 11.180339887498949 +```
    @@ -6396,401 +6397,401 @@ vectorDistance(10, 0, 5, 20, 0, 10); // 11.180339887498949 ## 📦 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(' ')}`, - red: `\x1b[31m${args.join(' ')}`, - green: `\x1b[32m${args.join(' ')}`, - yellow: `\x1b[33m${args.join(' ')}`, - blue: `\x1b[34m${args.join(' ')}`, - magenta: `\x1b[35m${args.join(' ')}`, - cyan: `\x1b[36m${args.join(' ')}`, - white: `\x1b[37m${args.join(' ')}`, - bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, - bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, - bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, - bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, - bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, - bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, - bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, - bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` -}); +const colorize = (...args) => ({ + black: `\x1b[30m${args.join(' ')}`, + red: `\x1b[31m${args.join(' ')}`, + green: `\x1b[32m${args.join(' ')}`, + yellow: `\x1b[33m${args.join(' ')}`, + blue: `\x1b[34m${args.join(' ')}`, + magenta: `\x1b[35m${args.join(' ')}`, + cyan: `\x1b[36m${args.join(' ')}`, + white: `\x1b[37m${args.join(' ')}`, + bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, + bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, + bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, + bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, + bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, + bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, + bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, + bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` +}); ```
    Examples ```js -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) -``` +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)); +const hasFlags = (...flags) => + flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); ```
    Examples ```js -// node myScript.js -s --test --cool=true -hasFlags('-s'); // true -hasFlags('--test', 'cool=true', '-s'); // true -hasFlags('special'); // false -``` +// node myScript.js -s --test --cool=true +hasFlags('-s'); // true +hasFlags('--test', 'cool=true', '-s'); // true +hasFlags('special'); // false +```

    [⬆ Back to top](#contents) -### 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. - +### 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 - ) - ); +const crypto = require('crypto'); +const hashNode = val => + new Promise(resolve => + setTimeout( + () => + resolve( + crypto + .createHash('sha256') + .update(val) + .digest('hex') + ), + 0 + ) + ); ```
    Examples ```js -hashNode(JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })).then(console.log); // '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393' -``` +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. - +### 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 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'; ```
    Examples ```js -const Stream = require('stream'); -isDuplexStream(new Stream.Duplex()); // true -``` +const Stream = require('stream'); +isDuplexStream(new Stream.Duplex()); // 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. - +### 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 isReadableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object'; +const isReadableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object'; ```
    Examples ```js -const fs = require('fs'); -isReadableStream(fs.createReadStream('test.txt')); // true -``` +const fs = require('fs'); +isReadableStream(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`. - +### 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'; +const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; ```
    Examples ```js -const fs = require('fs'); -isStream(fs.createReadStream('test.txt')); // true -``` +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; +const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; ```
    Examples ```js -isTravisCI(); // true (if code is running on Travis CI) -``` +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) => - fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); +const fs = require('fs'); +const JSONToFile = (obj, filename) => + fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); ```
    Examples ```js -JSONToFile({ test: 'is passed' }, 'testJsonFile'); // writes the object to 'testJsonFile.json' -``` +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 => - fs - .readFileSync(filename) - .toString('UTF8') - .split('\n'); +const fs = require('fs'); +const readFileLines = filename => + fs + .readFileSync(filename) + .toString('UTF8') + .split('\n'); ```
    Examples ```js -/* -contents of test.txt : - line1 - line2 - line3 - ___________________________ -*/ -let arr = readFileLines('test.txt'); -console.log(arr); // ['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`); +const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); ```
    Examples ```js -untildify('~/node'); // '/Users/aUser/node' -``` +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 = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) - ); +const crypto = require('crypto'); +const UUIDGeneratorNode = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) + ); ```
    Examples ```js -UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc' -``` +UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc' +```
    @@ -6801,134 +6802,134 @@ 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( - fn => ( - (f = obj[fn]), - (obj[fn] = function() { - return f.apply(obj); - }) - ) - ); +const bindAll = (obj, ...fns) => + fns.forEach( + fn => ( + (f = obj[fn]), + (obj[fn] = function() { + return f.apply(obj); + }) + ) + ); ```
    Examples ```js -var view = { - label: 'docs', - click: function() { - console.log('clicked ' + this.label); - } -}; -bindAll(view, 'click'); -jQuery(element).on('click', view.click); // Logs 'clicked docs' when clicked. -``` +var view = { + label: 'docs', + click: function() { + console.log('clicked ' + this.label); + } +}; +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 +```

    [⬆ Back to top](#contents) -### deepGet - -Returns the target value in a nested JSON object, based on the `keys` array. - -Compare the keys you want in the nested JSON object as an `Array`. -Use `Array.prototype.reduce()` to get value from nested JSON object one by one. -If the key exists in object, return target value, otherwise, return `null`. - +### deepGet + +Returns the target value in a nested JSON object, based on the `keys` array. + +Compare the keys you want in the nested JSON object as an `Array`. +Use `Array.prototype.reduce()` to get value from nested JSON object one by one. +If the key exists in object, return target value, otherwise, return `null`. + ```js -const deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), obj); +const deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), obj); ```
    Examples ```js -let index = 2; -const data = { - foo: { - foz: [1, 2, 3], - bar: { - baz: ['a', 'b', 'c'] - } - } -}; -deepGet(data, ['foo', 'foz', index]); // get 3 -deepGet(data, ['foo', 'bar', 'baz', 8, 'foz']); // null -``` +let index = 2; +const data = { + foo: { + foz: [1, 2, 3], + bar: { + baz: ['a', 'b', 'c'] + } + } +}; +deepGet(data, ['foo', 'foz', index]); // get 3 +deepGet(data, ['foo', 'bar', 'baz', 8, 'foz']); // null +```
    @@ -6994,58 +6995,58 @@ 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); +const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); ```
    Examples ```js -defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 } -``` +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. - +### 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); +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 -``` +const data = { + level1: { + level2: { + level3: 'some data' + } + } +}; +dig(data, 'level3'); // 'some data' +dig(data, 'level4'); // undefined +```
    @@ -7083,752 +7084,752 @@ 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)); +const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); ```
    Examples ```js -findKey( - { - barney: { age: 36, active: true }, - fred: { age: 40, active: false }, - pebbles: { age: 1, active: true } - }, - o => o['active'] -); // 'barney' -``` +findKey( + { + barney: { age: 36, active: true }, + fred: { age: 40, active: false }, + pebbles: { age: 1, active: true } + }, + 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) - .reverse() - .find(key => fn(obj[key], key, obj)); +const findLastKey = (obj, fn) => + Object.keys(obj) + .reverse() + .find(key => fn(obj[key], key, obj)); ```
    Examples ```js -findLastKey( - { - barney: { age: 36, active: true }, - fred: { age: 40, active: false }, - pebbles: { age: 1, active: true } - }, - o => o['active'] -); // 'pebbles' -``` +findLastKey( + { + barney: { age: 36, active: true }, + fred: { age: 40, active: false }, + pebbles: { age: 1, active: true } + }, + 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) => { - const pre = prefix.length ? prefix + '.' : ''; - if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); - else acc[pre + k] = obj[k]; - return acc; - }, {}); +const flattenObject = (obj, prefix = '') => + Object.keys(obj).reduce((acc, k) => { + const pre = prefix.length ? prefix + '.' : ''; + if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); + else acc[pre + k] = obj[k]; + return acc; + }, {}); ```
    Examples ```js -flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 } -``` +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)); +const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); ```
    Examples ```js -forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1 -``` +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) - .reverse() - .forEach(key => fn(obj[key], key, obj)); +const forOwnRight = (obj, fn) => + Object.keys(obj) + .reverse() + .forEach(key => fn(obj[key], key, obj)); ```
    Examples ```js -forOwnRight({ foo: 'bar', a: 1 }, v => console.log(v)); // 1, 'bar' -``` +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 - ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] - : Object.keys(obj) - ).filter(key => typeof obj[key] === 'function'); +const functions = (obj, inherited = false) => + (inherited + ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] + : Object.keys(obj) + ).filter(key => typeof obj[key] === 'function'); ```
    Examples ```js -function Foo() { - this.a = () => 1; - this.b = () => 2; -} -Foo.prototype.c = () => 3; -functions(new Foo()); // ['a', 'b'] -functions(new Foo(), true); // ['a', 'b', 'c'] -``` +function Foo() { + this.a = () => 1; + this.b = () => 2; +} +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 => - s - .replace(/\[([^\[\]]*)\]/g, '.$1.') - .split('.') - .filter(t => t !== '') - .reduce((prev, cur) => prev && prev[cur], from) - ); +const get = (from, ...selectors) => + [...selectors].map(s => + s + .replace(/\[([^\[\]]*)\]/g, '.$1.') + .split('.') + .filter(t => t !== '') + .reduce((prev, cur) => prev && prev[cur], from) + ); ```
    Examples ```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'] -``` +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) => { - const val = fn ? fn(obj[key]) : obj[key]; - acc[val] = acc[val] || []; - acc[val].push(key); - return acc; - }, {}); +const invertKeyValues = (obj, fn) => + Object.keys(obj).reduce((acc, key) => { + const val = fn ? fn(obj[key]) : obj[key]; + acc[val] = acc[val] || []; + acc[val].push(key); + return acc; + }, {}); ```
    Examples ```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' ] } -``` +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) => { - acc[key.toLowerCase()] = obj[key]; - return acc; - }, {}); +const lowercaseKeys = obj => + Object.keys(obj).reduce((acc, key) => { + acc[key.toLowerCase()] = obj[key]; + return acc; + }, {}); ```
    Examples ```js -const myObj = { Name: 'Adam', sUrnAME: 'Smith' }; -const myObjLower = lowercaseKeys(myObj); // {name: 'Adam', surname: 'Smith'}; -``` +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) => { - acc[fn(obj[k], k, obj)] = obj[k]; - return acc; - }, {}); +const mapKeys = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[fn(obj[k], k, obj)] = obj[k]; + return acc; + }, {}); ```
    Examples ```js -mapKeys({ a: 1, b: 2 }, (val, key) => key + val); // { a1: 1, b2: 2 } -``` +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) => { - acc[k] = fn(obj[k], k, obj); - return acc; - }, {}); +const mapValues = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[k] = fn(obj[k], k, obj); + return acc; + }, {}); ```
    Examples ```js -const users = { - fred: { user: 'fred', age: 40 }, - pebbles: { user: 'pebbles', age: 1 } -}; -mapValues(users, u => u.age); // { fred: 40, pebbles: 1 } -``` +const users = { + fred: { user: 'fred', age: 40 }, + 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]); +const matches = (obj, source) => + Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); ```
    Examples ```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 -``` +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( - key => - obj.hasOwnProperty(key) && fn - ? fn(obj[key], source[key], key, obj, source) - : obj[key] == source[key] - ); +const matchesWith = (obj, source, fn) => + Object.keys(source).every( + key => + obj.hasOwnProperty(key) && fn + ? fn(obj[key], source[key], key, obj, source) + : obj[key] == source[key] + ); ```
    Examples ```js -const isGreeting = val => /^h(?:i|ello)$/.test(val); -matchesWith( - { greeting: 'hello' }, - { greeting: 'hi' }, - (oV, sV) => isGreeting(oV) && isGreeting(sV) -); // true -``` +const isGreeting = val => /^h(?:i|ello)$/.test(val); +matchesWith( + { greeting: 'hello' }, + { 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( - (acc, obj) => - Object.keys(obj).reduce((a, k) => { - acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; - return acc; - }, {}), - {} - ); +const merge = (...objs) => + [...objs].reduce( + (acc, obj) => + Object.keys(obj).reduce((a, k) => { + acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; + return acc; + }, {}), + {} + ); ```
    Examples ```js -const object = { - a: [{ x: 2 }, { y: 4 }], - b: 1 -}; -const other = { - a: { z: 3 }, - b: [2, 3], - c: 'foo' -}; -merge(object, other); // { a: [ { x: 2 }, { y: 4 }, { z: 3 } ], b: [ 1, 2, 3 ], c: 'foo' } -``` +const object = { + a: [{ x: 2 }, { y: 4 }], + b: 1 +}; +const other = { + a: { z: 3 }, + b: [2, 3], + 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 - .filter(item => item[link] === id) - .map(item => ({ ...item, children: nest(items, item.id) })); +const nest = (items, id = null, link = 'parent_id') => + items + .filter(item => item[link] === id) + .map(item => ({ ...item, children: nest(items, item.id) })); ```
    Examples ```js -// One top level comment -const comments = [ - { id: 1, parent_id: null }, - { id: 2, parent_id: 1 }, - { id: 3, parent_id: 1 }, - { id: 4, parent_id: 2 }, - { id: 5, parent_id: 4 } -]; -const nestedComments = nest(comments); // [{ id: 1, parent_id: null, children: [...] }] -``` - +// One top level comment +const comments = [ + { id: 1, parent_id: null }, + { id: 2, parent_id: 1 }, + { id: 3, parent_id: 1 }, + { id: 4, parent_id: 2 }, + { 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), {}); +const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); ```
    Examples ```js -objectFromPairs([['a', 1], ['b', 2]]); // {a: 1, b: 2} -``` +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]]); +const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); ```
    Examples ```js -objectToPairs({ a: 1, b: 2 }); // [ ['a', 1], ['b', 2] ] -``` +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) - .filter(k => !arr.includes(k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const omit = (obj, arr) => + Object.keys(obj) + .filter(k => !arr.includes(k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); ```
    Examples ```js -omit({ a: 1, b: '2', c: 3 }, ['b']); // { 'a': 1, 'c': 3 } -``` +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) - .filter(k => !fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const omitBy = (obj, fn) => + Object.keys(obj) + .filter(k => !fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); ```
    Examples ```js -omitBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { b: '2' } -``` +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) => - props.reduce((acc, prop, i) => { - if (acc === 0) { - const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; - acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; - } - return acc; - }, 0) - ); +const orderBy = (arr, props, orders) => + [...arr].sort((a, b) => + props.reduce((acc, prop, i) => { + if (acc === 0) { + const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; + acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; + } + return acc; + }, 0) + ); ```
    Examples ```js -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}] -``` +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), {}); +const pick = (obj, arr) => + arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); ```
    Examples ```js -pick({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 } -``` +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) - .filter(k => fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const pickBy = (obj, fn) => + Object.keys(obj) + .filter(k => fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); ```
    Examples ```js -pickBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { 'a': 1, 'c': 3 } -``` +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( - (acc, key) => ({ - ...acc, - ...{ [keysMap[key] || key]: obj[key] } - }), - {} - ); +const renameKeys = (keysMap, obj) => + Object.keys(obj).reduce( + (acc, key) => ({ + ...acc, + ...{ [keysMap[key] || key]: obj[key] } + }), + {} + ); ```
    Examples ```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 } -``` +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); +const shallowClone = obj => Object.assign({}, obj); ```
    Examples ```js -const a = { x: true, y: 1 }; -const b = shallowClone(a); // a !== b -``` +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) - ? val.length - : val && typeof val === 'object' - ? val.size || val.length || Object.keys(val).length - : typeof val === 'string' - ? new Blob([val]).size - : 0; +const size = val => + Array.isArray(val) + ? val.length + : val && typeof val === 'object' + ? val.size || val.length || Object.keys(val).length + : typeof val === 'string' + ? new Blob([val]).size + : 0; ```
    Examples ```js -size([1, 2, 3, 4, 5]); // 5 -size('size'); // 4 -size({ one: 1, two: 2, three: 3 }); // 3 -``` +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); +const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); ```
    Examples ```js -transform( - { a: 1, b: 2, c: 1 }, - (r, v, k) => { - (r[v] || (r[v] = [])).push(k); - return r; - }, - {} -); // { '1': ['a', 'c'], '2': ['b'] } -``` +transform( + { a: 1, b: 2, c: 1 }, + (r, v, k) => { + (r[v] || (r[v] = [])).push(k); + return r; + }, + {} +); // { '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]); +const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); ```
    Examples ```js -truthCheckCollection([{ user: 'Tinky-Winky', sex: 'male' }, { user: 'Dipsy', sex: 'male' }], 'sex'); // true -``` +truthCheckCollection([{ user: 'Tinky-Winky', sex: 'male' }, { user: 'Dipsy', sex: 'male' }], 'sex'); // true +```
    @@ -7877,120 +7878,120 @@ 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; +const byteSize = str => new Blob([str]).size; ```
    Examples ```js -byteSize('😀'); // 4 -byteSize('Hello World'); // 11 -``` +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('')); +const capitalize = ([first, ...rest], lowerRest = false) => + first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); ```
    Examples ```js -capitalize('fooBar'); // 'FooBar' -capitalize('fooBar', true); // 'Foobar' -``` +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()); +const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); ```
    Examples ```js -capitalizeEveryWord('hello world!'); // 'Hello World!' -``` +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 occurrences 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 occurrences 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 - .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) - .split('\n') - .map(v => v.split(delimiter)); +const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => + data + .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) + .split('\n') + .map(v => v.split(delimiter)); ```
    Examples ```js -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']]; -``` +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']]; +```
    @@ -8031,452 +8032,452 @@ 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('')); +const decapitalize = ([first, ...rest], upperRest = false) => + first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); ```
    Examples ```js -decapitalize('FooBar'); // 'fooBar' -decapitalize('FooBar', true); // 'fOOBAR' -``` +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( - /[&<>'"]/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' - }[tag] || tag) - ); +const escapeHTML = str => + str.replace( + /[&<>'"]/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }[tag] || tag) + ); ```
    Examples ```js -escapeHTML('Me & you'); // '<a href="#">Me & you</a>' -``` +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, '\\$&'); +const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); ```
    Examples ```js -escapeRegExp('(test)'); // \\(test\\) -``` +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 - .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') - .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') - .toLowerCase(); +const fromCamelCase = (str, separator = '_') => + str + .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') + .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') + .toLowerCase(); ```
    Examples ```js -fromCamelCase('someDatabaseFieldName', ' '); // 'some database field name' -fromCamelCase('someLabelThatNeedsToBeCamelized', '-'); // 'some-label-that-needs-to-be-camelized' -fromCamelCase('someJavascriptProperty', '_'); // 'some_javascript_property' -``` +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)); +const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); ```
    Examples ```js -indentString('Lorem\nIpsum', 2); // ' Lorem\n Ipsum' -indentString('Lorem\nIpsum', 2, '_'); // '__Lorem\n__Ipsum' -``` +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); +const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); ```
    Examples ```js -isAbsoluteURL('https://google.com'); // true -isAbsoluteURL('ftp://www.myserver.net'); // true -isAbsoluteURL('/foo/bar'); // false -``` +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 => - str - .toLowerCase() - .replace(/[^a-z0-9]/gi, '') - .split('') - .sort() - .join(''); - return normalize(str1) === normalize(str2); -}; +const isAnagram = (str1, str2) => { + const normalize = str => + str + .toLowerCase() + .replace(/[^a-z0-9]/gi, '') + .split('') + .sort() + .join(''); + return normalize(str1) === normalize(str2); +}; ```
    Examples ```js -isAnagram('iceman', 'cinema'); // true -``` +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(); +const isLowerCase = str => str === str.toLowerCase(); ```
    Examples ```js -isLowerCase('abc'); // true -isLowerCase('a3@$'); // true -isLowerCase('Ab4'); // false -``` +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(); +const isUpperCase = str => str === str.toUpperCase(); ```
    Examples ```js -isUpperCase('ABC'); // true -isLowerCase('A3@$'); // true -isLowerCase('aB4'); // false -``` +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 - .split('') - .map((c, i) => fn(c, i, str)) - .join(''); +const mapString = (str, fn) => + str + .split('') + .map((c, i) => fn(c, i, str)) + .join(''); ```
    Examples ```js -mapString('lorem ipsum', c => c.toUpperCase()); // 'LOREM IPSUM' -``` +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); +const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); ```
    Examples ```js -mask(1234567890); // '******7890' -mask(1234567890, 3); // '*******890' -mask(1234567890, -4, '$'); // '$$$$567890' -``` +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); +const pad = (str, length, char = ' ') => + str.padStart((str.length + length) / 2, char).padEnd(length, char); ```
    Examples ```js -pad('cat', 8); // ' cat ' -pad(String(42), 6, '0'); // '004200' -pad('foobar', 3); // 'foobar' -``` +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') => - [1, -1].includes(Number(num)) ? word : plural; - if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); - return _pluralize(val, word, plural); -}; +const pluralize = (val, word, plural = word + 's') => { + const _pluralize = (num, word, plural = word + 's') => + [1, -1].includes(Number(num)) ? word : plural; + if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); + return _pluralize(val, word, plural); +}; ```
    Examples ```js -pluralize(0, 'apple'); // 'apples' -pluralize(1, 'apple'); // 'apple' -pluralize(2, 'apple'); // 'apples' -pluralize(2, 'person', 'people'); // 'people' - -const PLURALS = { - person: 'people', - radius: 'radii' -}; -const autoPluralize = pluralize(PLURALS); -autoPluralize(2, 'person'); // 'people' -``` +pluralize(0, 'apple'); // 'apples' +pluralize(1, 'apple'); // 'apple' +pluralize(2, 'apple'); // 'apples' +pluralize(2, 'person', 'people'); // 'people' + +const PLURALS = { + person: 'people', + radius: 'radii' +}; +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, ''); +const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); ```
    Examples ```js -removeNonASCII('äÄçÇéÉêlorem-ipsumöÖÐþúÚ'); // 'lorem-ipsum' -``` +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(''); +const reverseString = str => [...str].reverse().join(''); ```
    Examples ```js -reverseString('foobar'); // 'raboof' -``` +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(''); +const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); ```
    Examples ```js -sortCharactersInString('cabbage'); // 'aabbceg' -``` +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/); +const splitLines = str => str.split(/\r?\n/); ```
    Examples ```js -splitLines('This\nis a\nmultiline\nstring.\n'); // ['This', 'is a', 'multiline', 'string.' , ''] -``` +splitLines('This\nis a\nmultiline\nstring.\n'); // ['This', 'is a', 'multiline', 'string.' , ''] +```
    @@ -8517,197 +8518,197 @@ 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, ''); +const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); ```
    Examples ```js -stripHTMLTags('

    lorem ipsum

    '); // 'lorem ipsum' -``` +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 = - 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.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) - .join(''); - return s.slice(0, 1).toLowerCase() + s.slice(1); -}; +const toCamelCase = str => { + let 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(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) + .join(''); + return s.slice(0, 1).toLowerCase() + s.slice(1); +}; ```
    Examples ```js -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' -``` +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 && - 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 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('-'); ```
    Examples ```js -toKebabCase('camelCase'); // 'camel-case' -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" -``` +toKebabCase('camelCase'); // 'camel-case' +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 && - 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 toSnakeCase = 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('_'); ```
    Examples ```js -toSnakeCase('camelCase'); // 'camel_case' -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" -``` +toSnakeCase('camelCase'); // 'camel_case' +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; +const truncateString = (str, num) => + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; ```
    Examples ```js -truncateString('boomerang', 7); // 'boom...' -``` +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( - /&|<|>|'|"/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - ''': "'", - '"': '"' - }[tag] || tag) - ); +const unescapeHTML = str => + str.replace( + /&|<|>|'|"/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + ''': "'", + '"': '"' + }[tag] || tag) + ); ```
    Examples ```js -unescapeHTML('<a href="#">Me & you</a>'); // 'Me & you' -``` +unescapeHTML('<a href="#">Me & you</a>'); // 'Me & you' +```
    @@ -8742,24 +8743,24 @@ 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); +const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); ```
    Examples ```js -words('I love javaScript!!'); // ["I", "love", "javaScript"] -words('python, javaScript & coffee'); // ["python", "javaScript", "coffee"] -``` +words('I love javaScript!!'); // ["I", "love", "javaScript"] +words('python, javaScript & coffee'); // ["python", "javaScript", "coffee"] +```
    @@ -8770,440 +8771,440 @@ 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(); +const getType = v => + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); ```
    Examples ```js -getType(new Set([1, 2, 3])); // 'set' -``` +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; +const is = (type, val) => ![, null].includes(val) && val.constructor === type; ```
    Examples ```js -is(Array, [1]); // true -is(ArrayBuffer, new ArrayBuffer()); // true -is(Map, new Map()); // true -is(RegExp, /./g); // true -is(Set, new Set()); // true -is(WeakMap, new WeakMap()); // true -is(WeakSet, new WeakSet()); // true -is(String, ''); // true -is(String, new String('')); // true -is(Number, 1); // true -is(Number, new Number(1)); // true -is(Boolean, true); // true -is(Boolean, new Boolean(true)); // true -``` +is(Array, [1]); // true +is(ArrayBuffer, new ArrayBuffer()); // true +is(Map, new Map()); // true +is(RegExp, /./g); // true +is(Set, new Set()); // true +is(WeakMap, new WeakMap()); // true +is(WeakSet, new WeakSet()); // true +is(String, ''); // true +is(String, new String('')); // true +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'; +const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; ```
    Examples ```js -isArrayLike(document.querySelectorAll('.className')); // true -isArrayLike('abc'); // true -isArrayLike(null); // false -``` +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'; +const isBoolean = val => typeof val === 'boolean'; ```
    Examples ```js -isBoolean(null); // false -isBoolean(false); // true -``` +isBoolean(null); // false +isBoolean(false); // true +```

    [⬆ Back to top](#contents) -### isEmpty - -Returns true if the a value is an empty object, collection, 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, 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; +const isEmpty = val => val == null || !(Object.keys(val) || val).length; ```
    Examples ```js -isEmpty([]); // true -isEmpty({}); // true -isEmpty(''); // true -isEmpty([1, 2]); // false -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 -``` +isEmpty([]); // true +isEmpty({}); // true +isEmpty(''); // true +isEmpty([1, 2]); // false +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'; +const isFunction = val => typeof val === 'function'; ```
    Examples ```js -isFunction('x'); // false -isFunction(x => x); // true -``` +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; +const isNil = val => val === undefined || val === null; ```
    Examples ```js -isNil(null); // true -isNil(undefined); // true -``` +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; +const isNull = val => val === null; ```
    Examples ```js -isNull(null); // true -``` +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. -To safeguard against `NaN`, check if `val === val` (as `NaN` has a `typeof` equal to `number` and is the only value not equal to itself). - +### isNumber + +Checks if the given argument is a number. + +Use `typeof` to check if a value is classified as a number primitive. +To safeguard against `NaN`, check if `val === val` (as `NaN` has a `typeof` equal to `number` and is the only value not equal to itself). + ```js -const isNumber = val => typeof val === 'number' && val === val; +const isNumber = val => typeof val === 'number' && val === val; ```
    Examples ```js -isNumber(1); // true -isNumber('1'); // false -isNumber(NaN); // false -``` +isNumber(1); // true +isNumber('1'); // false +isNumber(NaN); // false +```

    [⬆ 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); +const isObject = obj => obj === Object(obj); ```
    Examples ```js -isObject([1, 2, 3, 4]); // true -isObject([]); // true -isObject(['Hello!']); // true -isObject({ a: 1 }); // true -isObject({}); // true -isObject(true); // false -``` +isObject([1, 2, 3, 4]); // true +isObject([]); // true +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'; +const isObjectLike = val => val !== null && typeof val === 'object'; ```
    Examples ```js -isObjectLike({}); // true -isObjectLike([1, 2, 3]); // true -isObjectLike(x => x); // false -isObjectLike(null); // false -``` +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; +const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; ```
    Examples ```js -isPlainObject({ a: 1 }); // true -isPlainObject(new Map()); // false -``` +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 && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function'; +const isPromiseLike = obj => + obj !== null && + (typeof obj === 'object' || typeof obj === 'function') && + typeof obj.then === 'function'; ```
    Examples ```js -isPromiseLike({ - then: function() { - return ''; - } -}); // true -isPromiseLike(null); // false -isPromiseLike({}); // false -``` +isPromiseLike({ + then: function() { + return ''; + } +}); // 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'; +const isSymbol = val => typeof val === 'symbol'; ```
    Examples ```js -isSymbol(Symbol('x')); // true -``` +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; +const isUndefined = val => val === undefined; ```
    Examples ```js -isUndefined(undefined); // true -``` +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 +```
    @@ -9214,144 +9215,144 @@ 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]); +const castArray = val => (Array.isArray(val) ? val : [val]); ```
    Examples ```js -castArray('foo'); // ['foo'] -castArray([1]); // [1] -``` +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); +const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); ```
    Examples ```js -const regExp = /lorem ipsum/gi; -const regExp2 = cloneRegExp(regExp); // /lorem ipsum/gi -``` +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(_)); +const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); ```
    Examples ```js -coalesce(null, undefined, '', NaN, 'Waldo'); // "" -``` +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); +const coalesceFactory = valid => (...args) => args.find(valid); ```
    Examples ```js -const customCoalesce = coalesceFactory(_ => ![null, undefined, '', NaN].includes(_)); -customCoalesce(undefined, null, NaN, '', 'Waldo'); // "Waldo" -``` +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 => - '#' + - shortHex - .slice(shortHex.startsWith('#') ? 1 : 0) - .split('') - .map(x => x + x) - .join(''); +const extendHex = shortHex => + '#' + + shortHex + .slice(shortHex.startsWith('#') ? 1 : 0) + .split('') + .map(x => x + x) + .join(''); ```
    Examples ```js -extendHex('#03f'); // '#0033ff' -extendHex('05a'); // '#0055aa' -``` +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( - (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), - {} - ); +const getURLParameters = url => + (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( + (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), + {} + ); ```
    Examples ```js -getURLParameters('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'} -getURLParameters('google.com'); // {} -``` +getURLParameters('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'} +getURLParameters('google.com'); // {} +```
    @@ -9398,219 +9399,219 @@ 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'); +const isBrowser = () => ![typeof window, typeof document].includes('undefined'); ```
    Examples ```js -isBrowser(); // true (browser) -isBrowser(); // false (Node) -``` +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 => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return performance.now() - before; - }); - return times.indexOf(Math.min(...times)); -}; +const mostPerformant = (fns, iterations = 10000) => { + const times = fns.map(fn => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return performance.now() - before; + }); + return times.indexOf(Math.min(...times)); +}; ```
    Examples ```js -mostPerformant([ - () => { - // Loops through the entire array before returning `false` - [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number'); - }, - () => { - // Only needs to reach index `1` before returning false - [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number'); - } -]); // 1 -``` +mostPerformant([ + () => { + // Loops through the entire array before returning `false` + [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number'); + }, + () => { + // Only needs to reach index `1` before returning false + [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]; +const nthArg = n => (...args) => args.slice(n)[0]; ```
    Examples ```js -const third = nthArg(2); -third(1, 2, 3); // 3 -third(1, 2); // undefined -const last = nthArg(-1); -last(1, 2, 3, 4, 5); // 5 -``` +const third = nthArg(2); +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 - .split(';') - .map(v => v.split('=')) - .reduce((acc, v) => { - acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); - return acc; - }, {}); +const parseCookie = str => + str + .split(';') + .map(v => v.split('=')) + .reduce((acc, v) => { + acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); + return acc; + }, {}); ```
    Examples ```js -parseCookie('foo=bar; equation=E%3Dmc%5E2'); // { foo: 'bar', equation: 'E=mc^2' } -``` +parseCookie('foo=bar; equation=E%3Dmc%5E2'); // { foo: 'bar', equation: 'E=mc^2' } +```
    @@ -9649,234 +9650,234 @@ 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); - return '#' + n.slice(0, 6); -}; +const randomHexColorCode = () => { + let n = (Math.random() * 0xfffff * 1000000).toString(16); + return '#' + n.slice(0, 6); +}; ```
    Examples ```js -randomHexColorCode(); // "#e34155" -``` +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'); +const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); ```
    Examples ```js -RGBToHex(255, 165, 1); // 'ffa501' -``` +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)}`; +const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; ```
    Examples ```js -serializeCookie('foo', 'bar'); // 'foo=bar' -``` +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'); - const r = callback(); - console.timeEnd('timeTaken'); - return r; -}; +const timeTaken = callback => { + console.time('timeTaken'); + const r = callback(); + console.timeEnd('timeTaken'); + return r; +}; ```
    Examples ```js -timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms -``` +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); +const toCurrency = (n, curr, LanguageFormat = undefined) => + Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); ```
    Examples ```js -toCurrency(123456.789, 'EUR'); // €123,456.79 | currency: Euro | currencyLangFormat: Local -toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79 | currency: US Dollar | currencyLangFormat: English (United States) -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 -``` +toCurrency(123456.789, 'EUR'); // €123,456.79 | currency: Euro | currencyLangFormat: Local +toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79 | currency: US Dollar | currencyLangFormat: English (United States) +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'); +const toDecimalMark = num => num.toLocaleString('en-US'); ```
    Examples ```js -toDecimalMark(12305030388.9087); // "12,305,030,388.909" -``` +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), - digits = [int % 10, int % 100], - ordinals = ['st', 'nd', 'rd', 'th'], - oPattern = [1, 2, 3, 4], - tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; - return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) - ? int + ordinals[digits[0] - 1] - : int + ordinals[3]; -}; +const toOrdinalSuffix = num => { + const int = parseInt(num), + digits = [int % 10, int % 100], + ordinals = ['st', 'nd', 'rd', 'th'], + oPattern = [1, 2, 3, 4], + tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; + return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) + ? int + ordinals[digits[0] - 1] + : int + ordinals[3]; +}; ```
    Examples ```js -toOrdinalSuffix('123'); // "123rd" -``` +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; +const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; ```
    Examples ```js -validateNumber('10'); // true -``` +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; +const yesNo = (val, def = false) => + /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; ```
    Examples ```js -yesNo('Y'); // true -yesNo('yes'); // true -yesNo('No'); // false -yesNo('Foo', true); // true -``` +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/docs/browser.html b/docs/browser.html index 14fe3479a..bc93e07d2 100644 --- a/docs/browser.html +++ b/docs/browser.html @@ -176,7 +176,7 @@ hub.emit.off('message', handler);

    currentURL

    Returns the current URL.

    Use window.location.href to get current URL.

    const currentURL = () => window.location.href;
     
    currentURL(); // 'https://google.com'
    -

    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.

    const detectDeviceType = () =>
    +

    detectDeviceType

    Detects whether 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.

    const detectDeviceType = () =>
       /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
         ? 'Mobile'
         : 'Desktop';
    diff --git a/docs/function.html b/docs/function.html
    index f391a6cc6..6c6291409 100644
    --- a/docs/function.html
    +++ b/docs/function.html
    @@ -153,6 +153,7 @@ console.log<
     
     
     
    +
     const lengthIs4 = checkProp(l => l === 4, 'length');
     lengthIs4([]); // false
     lengthIs4([1,2,3,4]); // true
    diff --git a/snippets/checkProp.md b/snippets/checkProp.md
    index 599399127..86a412cee 100644
    --- a/snippets/checkProp.md
    +++ b/snippets/checkProp.md
    @@ -18,6 +18,7 @@ const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]);
     
     
     
    +
     const lengthIs4 = checkProp(l => l === 4, 'length');
     lengthIs4([]); // false
     lengthIs4([1,2,3,4]); // true
    diff --git a/test/_30s.js b/test/_30s.js
    index c36428b8e..1be8796e9 100644
    --- a/test/_30s.js
    +++ b/test/_30s.js
    @@ -1,1537 +1,1537 @@
     const fs = typeof require !== "undefined" && require('fs');
     const crypto = typeof require !== "undefined" && require('crypto');
     
    -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);
    -const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
    -const arrayToCSV = (arr, delimiter = ',') =>
    -  arr
    -    .map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter))
    -    .join('\n');
    -const arrayToHtmlList = (arr, listID) =>
    -  (el => (
    -    (el = document.querySelector('#' + 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 attempt = (fn, ...args) => { - try { - return fn(...args); - } catch (e) { - return e instanceof Error ? e : new Error(e); - } -}; -const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; -const averageBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / - arr.length; -const bifurcate = (arr, filter) => - arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); -const bifurcateBy = (arr, fn) => - arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); -const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); -const bindAll = (obj, ...fns) => - fns.forEach( - fn => ( - (f = obj[fn]), - (obj[fn] = function() { - return f.apply(obj); - }) - ) - ); -const bindKey = (context, fn, ...boundArgs) => (...args) => - context[fn].apply(context, [...boundArgs, ...args]); -const binomialCoefficient = (n, k) => { - if (Number.isNaN(n) || Number.isNaN(k)) return NaN; - if (k < 0 || k > n) return 0; - if (k === 0 || k === n) return 1; - if (k === 1 || k === n - 1) return n; - if (n - k < k) k = n - k; - let res = n; - for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; - return Math.round(res); -}; -const bottomVisible = () => - document.documentElement.clientHeight + window.scrollY >= - (document.documentElement.scrollHeight || document.documentElement.clientHeight); -const btoa = str => Buffer.from(str, 'binary').toString('base64'); -const byteSize = str => new Blob([str]).size; +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); +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; +const arrayToCSV = (arr, delimiter = ',') => + arr + .map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter)) + .join('\n'); +const arrayToHtmlList = (arr, listID) => + (el => ( + (el = document.querySelector('#' + 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 attempt = (fn, ...args) => { + try { + return fn(...args); + } catch (e) { + return e instanceof Error ? e : new Error(e); + } +}; +const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; +const averageBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / + arr.length; +const bifurcate = (arr, filter) => + arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); +const bifurcateBy = (arr, fn) => + arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); +const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); +const bindAll = (obj, ...fns) => + fns.forEach( + fn => ( + (f = obj[fn]), + (obj[fn] = function() { + return f.apply(obj); + }) + ) + ); +const bindKey = (context, fn, ...boundArgs) => (...args) => + context[fn].apply(context, [...boundArgs, ...args]); +const binomialCoefficient = (n, k) => { + if (Number.isNaN(n) || Number.isNaN(k)) return NaN; + if (k < 0 || k > n) return 0; + if (k === 0 || k === n) return 1; + if (k === 1 || k === n - 1) return n; + if (n - k < k) k = n - k; + let res = n; + for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; + return Math.round(res); +}; +const bottomVisible = () => + document.documentElement.clientHeight + window.scrollY >= + (document.documentElement.scrollHeight || document.documentElement.clientHeight); +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 checkProp = (predicate, prop) => obj => !!predicate(obj[prop]); -const chunk = (arr, size) => - Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => - arr.slice(i * size, i * size + size) - ); -const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); -const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); -const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); -const coalesceFactory = valid => (...args) => args.find(valid); +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 checkProp = (predicate, prop) => obj => !!predicate(obj[prop]); +const chunk = (arr, size) => + Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => + arr.slice(i * size, i * size + size) + ); +const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); +const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); +const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); +const coalesceFactory = valid => (...args) => args.find(valid); const collectInto = fn => (...args) => fn(args); -const colorize = (...args) => ({ - black: `\x1b[30m${args.join(' ')}`, - red: `\x1b[31m${args.join(' ')}`, - green: `\x1b[32m${args.join(' ')}`, - yellow: `\x1b[33m${args.join(' ')}`, - blue: `\x1b[34m${args.join(' ')}`, - magenta: `\x1b[35m${args.join(' ')}`, - cyan: `\x1b[36m${args.join(' ')}`, - white: `\x1b[37m${args.join(' ')}`, - bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, - bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, - bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, - bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, - bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, - bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, - bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, - 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 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 => { - const el = document.createElement('textarea'); - el.value = str; - el.setAttribute('readonly', ''); - el.style.position = 'absolute'; - el.style.left = '-9999px'; - document.body.appendChild(el); - const selected = - document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; - el.select(); - document.execCommand('copy'); - document.body.removeChild(el); - if (selected) { - document.getSelection().removeAllRanges(); - 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 counter = (selector, start, end, step = 1, duration = 2000) => { - let current = start, - _step = (end - start) * step < 0 ? -step : step, - timer = setInterval(() => { - current += _step; - document.querySelector(selector).innerHTML = current; - if (current >= end) document.querySelector(selector).innerHTML = end; - if (current >= end) clearInterval(timer); - }, 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'); - el.innerHTML = str; - return el.firstElementChild; -}; -const createEventHub = () => ({ - hub: Object.create(null), - emit(event, data) { - (this.hub[event] || []).forEach(handler => handler(data)); - }, - on(event, handler) { - if (!this.hub[event]) this.hub[event] = []; - this.hub[event].push(handler); - }, - off(event, handler) { - const i = (this.hub[event] || []).findIndex(h => h === handler); - 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 debounce = (fn, ms = 0) => { - let timeoutId; - return function(...args) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -}; -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 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 deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), 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 delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); -const detectDeviceType = () => - /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) - ? 'Mobile' - : 'Desktop'; -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.map(fn).filter(el => !s.has(el)); -}; -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 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); -const dropRight = (arr, n = 1) => arr.slice(0, -n); -const dropRightWhile = (arr, func) => { - while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); - return arr; -}; -const dropWhile = (arr, func) => { - while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); - return arr; -}; -const elementContains = (parent, child) => parent !== child && parent.contains(child); -const elementIsVisibleInViewport = (el, partiallyVisible = false) => { - const { top, left, bottom, right } = el.getBoundingClientRect(); - const { innerHeight, innerWidth } = window; - return partiallyVisible - ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && - ((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 equals = (a, b) => { - if (a === b) return true; - if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); - if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; - if (a === null || a === undefined || b === null || b === undefined) return false; - if (a.prototype !== b.prototype) return false; - let keys = Object.keys(a); - if (keys.length !== Object.keys(b).length) return false; - return keys.every(k => equals(a[k], b[k])); -}; -const escapeHTML = str => - str.replace( - /[&<>'"]/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' - }[tag] || tag) - ); -const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); -const extendHex = shortHex => - '#' + - shortHex - .slice(shortHex.startsWith('#') ? 1 : 0) - .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 fibonacci = n => - Array.from({ length: n }).reduce( - (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), - [] - ); +const colorize = (...args) => ({ + black: `\x1b[30m${args.join(' ')}`, + red: `\x1b[31m${args.join(' ')}`, + green: `\x1b[32m${args.join(' ')}`, + yellow: `\x1b[33m${args.join(' ')}`, + blue: `\x1b[34m${args.join(' ')}`, + magenta: `\x1b[35m${args.join(' ')}`, + cyan: `\x1b[36m${args.join(' ')}`, + white: `\x1b[37m${args.join(' ')}`, + bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, + bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, + bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, + bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, + bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, + bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, + bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, + 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 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 => { + const el = document.createElement('textarea'); + el.value = str; + el.setAttribute('readonly', ''); + el.style.position = 'absolute'; + el.style.left = '-9999px'; + document.body.appendChild(el); + const selected = + document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); + if (selected) { + document.getSelection().removeAllRanges(); + 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 counter = (selector, start, end, step = 1, duration = 2000) => { + let current = start, + _step = (end - start) * step < 0 ? -step : step, + timer = setInterval(() => { + current += _step; + document.querySelector(selector).innerHTML = current; + if (current >= end) document.querySelector(selector).innerHTML = end; + if (current >= end) clearInterval(timer); + }, Math.abs(Math.floor(duration / (end - start)))); + return timer; +}; + +const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); +const createElement = str => { + const el = document.createElement('div'); + el.innerHTML = str; + return el.firstElementChild; +}; +const createEventHub = () => ({ + hub: Object.create(null), + emit(event, data) { + (this.hub[event] || []).forEach(handler => handler(data)); + }, + on(event, handler) { + if (!this.hub[event]) this.hub[event] = []; + this.hub[event].push(handler); + }, + off(event, handler) { + const i = (this.hub[event] || []).findIndex(h => h === handler); + if (i > -1) this.hub[event].splice(i, 1); + } +}); +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 debounce = (fn, ms = 0) => { + let timeoutId; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; +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 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 deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), 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 delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); +const detectDeviceType = () => + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + ? 'Mobile' + : 'Desktop'; +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.map(fn).filter(el => !s.has(el)); +}; +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 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); +const dropRight = (arr, n = 1) => arr.slice(0, -n); +const dropRightWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); + return arr; +}; +const dropWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); + return arr; +}; +const elementContains = (parent, child) => parent !== child && parent.contains(child); +const elementIsVisibleInViewport = (el, partiallyVisible = false) => { + const { top, left, bottom, right } = el.getBoundingClientRect(); + const { innerHeight, innerWidth } = window; + return partiallyVisible + ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && + ((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 equals = (a, b) => { + if (a === b) return true; + if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); + if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; + if (a === null || a === undefined || b === null || b === undefined) return false; + if (a.prototype !== b.prototype) return false; + let keys = Object.keys(a); + if (keys.length !== Object.keys(b).length) return false; + return keys.every(k => equals(a[k], b[k])); +}; +const escapeHTML = str => + str.replace( + /[&<>'"]/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }[tag] || tag) + ); +const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); +const extendHex = shortHex => + '#' + + shortHex + .slice(shortHex.startsWith('#') ? 1 : 0) + .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 fibonacci = n => + Array.from({ length: n }).reduce( + (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), + [] + ); const filterFalsy = arr => arr.filter(Boolean); -const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); -const filterNonUniqueBy = (arr, fn) => - arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); -const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); -const findLast = (arr, fn) => arr.filter(fn).pop(); -const findLastIndex = (arr, fn) => - arr - .map((val, i) => [i, val]) - .filter(([i, val]) => fn(val, i, arr)) - .pop()[0]; -const findLastKey = (obj, fn) => - Object.keys(obj) - .reverse() - .find(key => fn(obj[key], key, obj)); -const flatten = (arr, depth = 1) => - arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); -const flattenObject = (obj, prefix = '') => - Object.keys(obj).reduce((acc, k) => { - const pre = prefix.length ? prefix + '.' : ''; - if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); - else acc[pre + k] = obj[k]; - return acc; - }, {}); +const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); +const filterNonUniqueBy = (arr, fn) => + arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); +const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); +const findLast = (arr, fn) => arr.filter(fn).pop(); +const findLastIndex = (arr, fn) => + arr + .map((val, i) => [i, val]) + .filter(([i, val]) => fn(val, i, arr)) + .pop()[0]; +const findLastKey = (obj, fn) => + Object.keys(obj) + .reverse() + .find(key => fn(obj[key], key, obj)); +const flatten = (arr, depth = 1) => + arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); +const flattenObject = (obj, prefix = '') => + Object.keys(obj).reduce((acc, k) => { + const pre = prefix.length ? prefix + '.' : ''; + if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); + else acc[pre + k] = obj[k]; + return acc; + }, {}); const flip = fn => (first, ...rest) => fn(...rest, first); -const forEachRight = (arr, callback) => - arr - .slice(0) - .reverse() - .forEach(callback); -const formatDuration = ms => { - if (ms < 0) ms = -ms; - const time = { - day: Math.floor(ms / 86400000), - hour: Math.floor(ms / 3600000) % 24, - minute: Math.floor(ms / 60000) % 60, - second: Math.floor(ms / 1000) % 60, - millisecond: Math.floor(ms) % 1000 - }; - return Object.entries(time) - .filter(val => val[1] !== 0) - .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) - .join(', '); -}; -const formToObject = form => - Array.from(new FormData(form)).reduce( - (acc, [key, value]) => ({ - ...acc, - [key]: value - }), - {} - ); -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') - .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') - .toLowerCase(); -const functionName = fn => (console.debug(fn.name), fn); -const functions = (obj, inherited = false) => - (inherited - ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] - : Object.keys(obj) - ).filter(key => typeof obj[key] === 'function'); -const gcd = (...arr) => { - const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); - return [...arr].reduce((a, b) => _gcd(a, b)); -}; -const geometricProgression = (end, start = 1, step = 2) => - Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( - (v, i) => start * step ** i - ); -const get = (from, ...selectors) => - [...selectors].map(s => - s - .replace(/\[([^\[\]]*)\]/g, '.$1.') - .split('.') - .filter(t => t !== '') - .reduce((prev, cur) => prev && prev[cur], from) - ); -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 getScrollPosition = (el = window) => ({ - x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, - y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop -}); -const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; -const getType = v => - v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); -const getURLParameters = url => - (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( - (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), - {} - ); -const groupBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { - acc[val] = (acc[val] || []).concat(arr[i]); - return acc; - }, {}); -const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; -const hasClass = (el, className) => el.classList.contains(className); -const hasFlags = (...flags) => - flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); -const hashBrowser = val => - crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { - let hexes = [], - view = new DataView(h); - for (let i = 0; i < view.byteLength; i += 4) - 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 head = arr => arr[0]; -const hexToRGB = hex => { - let alpha = false, - h = hex.slice(hex.startsWith('#') ? 1 : 0); - if (h.length === 3) h = [...h].map(x => x + x).join(''); - else if (h.length === 8) alpha = true; - h = parseInt(h, 16); - return ( - 'rgb' + - (alpha ? 'a' : '') + - '(' + - (h >>> (alpha ? 24 : 16)) + - ', ' + - ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + - ', ' + - ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + - (alpha ? `, ${h & 0x000000ff}` : '') + - ')' - ); -}; -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 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); -const initialize2DArray = (w, h, val = null) => - Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); -const initializeArrayWithRange = (end, start = 0, step = 1) => - Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); -const initializeArrayWithRangeRight = (end, start = 0, step = 1) => - Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( - (v, i, arr) => (arr.length - i - 1) * step + start - ); -const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); -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) => { - const s = new Set(b); - return a.filter(x => s.has(x)); -}; -const intersectionBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => s.has(fn(x))); -}; -const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); -const invertKeyValues = (obj, fn) => - Object.keys(obj).reduce((acc, key) => { - const val = fn ? fn(obj[key]) : obj[key]; - acc[val] = acc[val] || []; - acc[val].push(key); - return acc; - }, {}); -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 isAnagram = (str1, str2) => { - const normalize = str => - str - .toLowerCase() - .replace(/[^a-z0-9]/gi, '') - .split('') - .sort() - .join(''); - return normalize(str1) === normalize(str2); -}; -const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; -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 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 isNil = val => val === undefined || val === null; -const isNull = val => val === null; -const isNumber = val => typeof val === 'number' && val === val; -const isObject = obj => obj === Object(obj); -const isObjectLike = val => val !== null && typeof val === 'object'; -const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; -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 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 isSorted = arr => { - let direction = -(arr[0] - arr[1]); - for (let [i, val] of arr.entries()) { - direction = !direction ? -(arr[i - 1] - arr[i]) : direction; - if (i === arr.length - 1) return !direction ? 0 : direction; - 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 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 join = (arr, separator = ',', end = separator) => - arr.reduce( - (acc, val, i) => - i === arr.length - 2 - ? acc + val + end - : i === arr.length - 1 - ? acc + val - : 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 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 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), {}) - ))(); -const mapString = (str, fn) => - str - .split('') - .map((c, i) => fn(c, i, str)) - .join(''); -const mapValues = (obj, fn) => - Object.keys(obj).reduce((acc, k) => { - acc[k] = fn(obj[k], k, obj); - return acc; - }, {}); -const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); -const matches = (obj, source) => - Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); -const matchesWith = (obj, source, fn) => - Object.keys(source).every( - key => - obj.hasOwnProperty(key) && fn - ? fn(obj[key], source[key], key, obj, source) - : 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 maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); -const median = arr => { - const mid = Math.floor(arr.length / 2), - nums = [...arr].sort((a, b) => a - b); - return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; -}; -const memoize = fn => { - const cache = new Map(); - const cached = function(val) { - return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); - }; - cached.cache = cache; - return cached; -}; -const merge = (...objs) => - [...objs].reduce( - (acc, obj) => - Object.keys(obj).reduce((a, k) => { - acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; - return acc; - }, {}), - {} - ); -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 minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); -const mostPerformant = (fns, iterations = 10000) => { - const times = fns.map(fn => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return performance.now() - before; - }); - return times.indexOf(Math.min(...times)); -}; -const negate = func => (...args) => !func(...args); -const nest = (items, id = null, link = 'parent_id') => - items - .filter(item => item[link] === id) - .map(item => ({ ...item, children: nest(items, item.id) })); -const nodeListToArray = nodeList => [...nodeList]; -const none = (arr, fn = Boolean) => !arr.some(fn); -const nthArg = n => (...args) => args.slice(n)[0]; -const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; -const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); -const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); -const observeMutations = (element, callback, options) => { - const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); - observer.observe( - element, - Object.assign( - { - childList: true, - attributes: true, - attributeOldValue: true, - characterData: true, - characterDataOldValue: true, - subtree: true - }, - options - ) - ); - return observer; -}; -const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); -const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; -const omit = (obj, arr) => - Object.keys(obj) - .filter(k => !arr.includes(k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); -const omitBy = (obj, fn) => - Object.keys(obj) - .filter(k => !fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); -const on = (el, evt, fn, opts = {}) => { - const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); - 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; - const mousemoveHandler = () => { - const now = performance.now(); - if (now - lastTime < 20) - (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); - lastTime = now; - }; - document.addEventListener('touchstart', () => { - if (type === 'touch') return; - (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); - }); -}; -const orderBy = (arr, props, orders) => - [...arr].sort((a, b) => - props.reduce((acc, prop, i) => { - if (acc === 0) { - const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; - acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; - } - return acc; - }, 0) - ); -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 parseCookie = str => - str - .split(';') - .map(v => v.split('=')) - .reduce((acc, v) => { - acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); - return acc; - }, {}); -const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); -const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); -const partition = (arr, fn) => - arr.reduce( - (acc, val, i, arr) => { - acc[fn(val, i, arr) ? 0 : 1].push(val); - return acc; - }, - [[], []] - ); -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( - (acc, item, i) => - acc.concat( - permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) - ), - [] - ); -}; -const pick = (obj, arr) => - arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); -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 pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); -const pluralize = (val, word, plural = word + 's') => { - const _pluralize = (num, word, plural = word + 's') => - [1, -1].includes(Number(num)) ? word : plural; - if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); - return _pluralize(val, word, plural); -}; -const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); -const prefix = prop => { - const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); - const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; - const i = prefixes.findIndex( - prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' - ); - return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; -}; -const prettyBytes = (num, precision = 3, addSpace = true) => { - const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; - const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); - const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); - return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; -}; -const primes = num => { - let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), - sqroot = Math.floor(Math.sqrt(num)), - numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); - numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); - return arr; -}; -const promisify = func => (...args) => - new Promise((resolve, reject) => - func(...args, (err, result) => (err ? reject(err) : resolve(result))) - ); -const pull = (arr, ...args) => { - let argState = Array.isArray(args[0]) ? args[0] : args; - let pulled = arr.filter((v, i) => !argState.includes(v)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); -}; -const pullAtIndex = (arr, pullArr) => { - let removed = []; - let pulled = arr - .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) - .filter((v, i) => !pullArr.includes(i)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); - return removed; -}; -const pullAtValue = (arr, pullArr) => { - let removed = [], - pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), - mutateTo = arr.filter((v, i) => !pullArr.includes(v)); - arr.length = 0; - mutateTo.forEach(v => arr.push(v)); - return removed; -}; -const pullBy = (arr, ...args) => { - const length = args.length; - let fn = length > 1 ? args[length - 1] : undefined; - fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; - let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); - let pulled = arr.filter((v, i) => !argState.includes(fn(v))); - arr.length = 0; - pulled.forEach(v => arr.push(v)); -}; -const radsToDegrees = rad => (rad * 180.0) / Math.PI; -const randomHexColorCode = () => { - let n = (Math.random() * 0xfffff * 1000000).toString(16); - return '#' + n.slice(0, 6); -}; -const randomIntArrayInRange = (min, max, n = 1) => - Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); -const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; -const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; - -const readFileLines = filename => - fs - .readFileSync(filename) - .toString('UTF8') - .split('\n'); -const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); -const recordAnimationFrames = (callback, autoStart = true) => { - let running = true, - raf; - const stop = () => { - running = false; - cancelAnimationFrame(raf); - }; - const start = () => { - running = true; - run(); - }; - const run = () => { - raf = requestAnimationFrame(() => { - callback(); - if (running) run(); - }); - }; - if (autoStart) start(); - return { start, stop }; -}; -const redirect = (url, asLink = true) => - asLink ? (window.location.href = url) : window.location.replace(url); -const reducedFilter = (data, keys, fn) => - data.filter(fn).map(el => - keys.reduce((acc, key) => { - acc[key] = el[key]; - 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 removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); -const renameKeys = (keysMap, obj) => - Object.keys(obj).reduce( - (acc, key) => ({ - ...acc, - ...{ [keysMap[key] || key]: obj[key] } - }), - {} - ); -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 runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); -const sample = arr => arr[Math.floor(Math.random() * arr.length)]; -const sampleSize = ([...arr], n = 1) => { - let m = arr.length; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr.slice(0, n); -}; -const scrollToTop = () => { - const c = document.documentElement.scrollTop || document.body.scrollTop; - if (c > 0) { - window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c / 8); - } -}; -const sdbm = str => { - let arr = str.split(''); - return arr.reduce( - (hashCode, currentVal) => - (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), - 0 - ); -}; -const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; -const serializeForm = form => - Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&'); -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 show = (...el) => [...el].forEach(e => (e.style.display = '')); -const shuffle = ([...arr]) => { - let m = arr.length; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr; -}; -const similarity = (arr, values) => arr.filter(v => values.includes(v)); -const size = val => - Array.isArray(val) - ? val.length - : val && typeof val === 'object' - ? val.size || val.length || Object.keys(val).length - : typeof val === 'string' - ? new Blob([val]).size - : 0; -const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); -const smoothScroll = element => - document.querySelector(element).scrollIntoView({ - behavior: 'smooth' - }); -const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); -const sortedIndex = (arr, n) => { - const isDescending = arr[0] > arr[arr.length - 1]; - const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); - return index === -1 ? arr.length : index; -}; -const sortedIndexBy = (arr, n, fn) => { - const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); - const val = fn(n); - const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); - return index === -1 ? arr.length : index; -}; -const sortedLastIndex = (arr, n) => { - const isDescending = arr[0] > arr[arr.length - 1]; - const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); - return index === -1 ? 0 : arr.length - index; -}; -const sortedLastIndexBy = (arr, n, fn) => { - const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); - const val = fn(n); - const index = arr - .map(fn) - .reverse() - .findIndex(el => (isDescending ? val <= el : val >= el)); - return index === -1 ? 0 : arr.length - index; -}; -const splitLines = str => str.split(/\r?\n/); +const forEachRight = (arr, callback) => + arr + .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 formToObject = form => + Array.from(new FormData(form)).reduce( + (acc, [key, value]) => ({ + ...acc, + [key]: value + }), + {} + ); +const formatDuration = ms => { + if (ms < 0) ms = -ms; + const time = { + day: Math.floor(ms / 86400000), + hour: Math.floor(ms / 3600000) % 24, + minute: Math.floor(ms / 60000) % 60, + second: Math.floor(ms / 1000) % 60, + millisecond: Math.floor(ms) % 1000 + }; + return Object.entries(time) + .filter(val => val[1] !== 0) + .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) + .join(', '); +}; +const fromCamelCase = (str, separator = '_') => + str + .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') + .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') + .toLowerCase(); +const functionName = fn => (console.debug(fn.name), fn); +const functions = (obj, inherited = false) => + (inherited + ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] + : Object.keys(obj) + ).filter(key => typeof obj[key] === 'function'); +const gcd = (...arr) => { + const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); + return [...arr].reduce((a, b) => _gcd(a, b)); +}; +const geometricProgression = (end, start = 1, step = 2) => + Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( + (v, i) => start * step ** i + ); +const get = (from, ...selectors) => + [...selectors].map(s => + s + .replace(/\[([^\[\]]*)\]/g, '.$1.') + .split('.') + .filter(t => t !== '') + .reduce((prev, cur) => prev && prev[cur], from) + ); +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 getScrollPosition = (el = window) => ({ + x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, + y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop +}); +const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; +const getType = v => + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); +const getURLParameters = url => + (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( + (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), + {} + ); +const groupBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { + acc[val] = (acc[val] || []).concat(arr[i]); + return acc; + }, {}); +const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; +const hasClass = (el, className) => el.classList.contains(className); +const hasFlags = (...flags) => + flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); +const hashBrowser = val => + crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { + let hexes = [], + view = new DataView(h); + for (let i = 0; i < view.byteLength; i += 4) + 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 head = arr => arr[0]; +const hexToRGB = hex => { + let alpha = false, + h = hex.slice(hex.startsWith('#') ? 1 : 0); + if (h.length === 3) h = [...h].map(x => x + x).join(''); + else if (h.length === 8) alpha = true; + h = parseInt(h, 16); + return ( + 'rgb' + + (alpha ? 'a' : '') + + '(' + + (h >>> (alpha ? 24 : 16)) + + ', ' + + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + + ', ' + + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + + (alpha ? `, ${h & 0x000000ff}` : '') + + ')' + ); +}; +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 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); +const initialize2DArray = (w, h, val = null) => + Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); +const initializeArrayWithRange = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); +const initializeArrayWithRangeRight = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( + (v, i, arr) => (arr.length - i - 1) * step + start + ); +const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); +const initializeNDArray = (val, ...args) => + args.length === 0 + ? val + : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); +const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); +const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); +const intersection = (a, b) => { + const s = new Set(b); + return a.filter(x => s.has(x)); +}; +const intersectionBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => s.has(fn(x))); +}; +const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); +const invertKeyValues = (obj, fn) => + Object.keys(obj).reduce((acc, key) => { + const val = fn ? fn(obj[key]) : obj[key]; + acc[val] = acc[val] || []; + acc[val].push(key); + return acc; + }, {}); +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 isAnagram = (str1, str2) => { + const normalize = str => + str + .toLowerCase() + .replace(/[^a-z0-9]/gi, '') + .split('') + .sort() + .join(''); + return normalize(str1) === normalize(str2); +}; +const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; +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 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 isNil = val => val === undefined || val === null; +const isNull = val => val === null; +const isNumber = val => typeof val === 'number' && val === val; +const isObject = obj => obj === Object(obj); +const isObjectLike = val => val !== null && typeof val === 'object'; +const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; +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 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 isSorted = arr => { + let direction = -(arr[0] - arr[1]); + for (let [i, val] of arr.entries()) { + direction = !direction ? -(arr[i - 1] - arr[i]) : direction; + if (i === arr.length - 1) return !direction ? 0 : direction; + 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 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 join = (arr, separator = ',', end = separator) => + arr.reduce( + (acc, val, i) => + i === arr.length - 2 + ? acc + val + end + : i === arr.length - 1 + ? acc + val + : acc + val + separator, + '' + ); +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 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 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), {}) + ))(); +const mapString = (str, fn) => + str + .split('') + .map((c, i) => fn(c, i, str)) + .join(''); +const mapValues = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[k] = fn(obj[k], k, obj); + return acc; + }, {}); +const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); +const matches = (obj, source) => + Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); +const matchesWith = (obj, source, fn) => + Object.keys(source).every( + key => + obj.hasOwnProperty(key) && fn + ? fn(obj[key], source[key], key, obj, source) + : 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 maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); +const median = arr => { + const mid = Math.floor(arr.length / 2), + nums = [...arr].sort((a, b) => a - b); + return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; +}; +const memoize = fn => { + const cache = new Map(); + const cached = function(val) { + return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); + }; + cached.cache = cache; + return cached; +}; +const merge = (...objs) => + [...objs].reduce( + (acc, obj) => + Object.keys(obj).reduce((a, k) => { + acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; + return acc; + }, {}), + {} + ); +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 minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); +const mostPerformant = (fns, iterations = 10000) => { + const times = fns.map(fn => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return performance.now() - before; + }); + return times.indexOf(Math.min(...times)); +}; +const negate = func => (...args) => !func(...args); +const nest = (items, id = null, link = 'parent_id') => + items + .filter(item => item[link] === id) + .map(item => ({ ...item, children: nest(items, item.id) })); +const nodeListToArray = nodeList => [...nodeList]; +const none = (arr, fn = Boolean) => !arr.some(fn); +const nthArg = n => (...args) => args.slice(n)[0]; +const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; +const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); +const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); +const observeMutations = (element, callback, options) => { + const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); + observer.observe( + element, + Object.assign( + { + childList: true, + attributes: true, + attributeOldValue: true, + characterData: true, + characterDataOldValue: true, + subtree: true + }, + options + ) + ); + return observer; +}; +const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); +const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; +const omit = (obj, arr) => + Object.keys(obj) + .filter(k => !arr.includes(k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const omitBy = (obj, fn) => + Object.keys(obj) + .filter(k => !fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const on = (el, evt, fn, opts = {}) => { + const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); + el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); + if (opts.target) return delegatorFn; +}; +const onUserInputChange = callback => { + let type = 'mouse', + lastTime = 0; + const mousemoveHandler = () => { + const now = performance.now(); + if (now - lastTime < 20) + (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); + lastTime = now; + }; + document.addEventListener('touchstart', () => { + if (type === 'touch') return; + (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) => { + if (acc === 0) { + const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; + acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; + } + return acc; + }, 0) + ); +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 parseCookie = str => + str + .split(';') + .map(v => v.split('=')) + .reduce((acc, v) => { + acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); + return acc; + }, {}); +const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); +const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); +const partition = (arr, fn) => + arr.reduce( + (acc, val, i, arr) => { + acc[fn(val, i, arr) ? 0 : 1].push(val); + return acc; + }, + [[], []] + ); +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( + (acc, item, i) => + acc.concat( + permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) + ), + [] + ); +}; +const pick = (obj, arr) => + arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); +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 pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); +const pluralize = (val, word, plural = word + 's') => { + const _pluralize = (num, word, plural = word + 's') => + [1, -1].includes(Number(num)) ? word : plural; + if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); + return _pluralize(val, word, plural); +}; +const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); +const prefix = prop => { + const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); + const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; + const i = prefixes.findIndex( + prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' + ); + return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; +}; +const prettyBytes = (num, precision = 3, addSpace = true) => { + const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; + const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); + const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); + return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; +}; +const primes = num => { + let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), + sqroot = Math.floor(Math.sqrt(num)), + numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); + numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); + return arr; +}; +const promisify = func => (...args) => + new Promise((resolve, reject) => + func(...args, (err, result) => (err ? reject(err) : resolve(result))) + ); +const pull = (arr, ...args) => { + let argState = Array.isArray(args[0]) ? args[0] : args; + let pulled = arr.filter((v, i) => !argState.includes(v)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); +}; +const pullAtIndex = (arr, pullArr) => { + let removed = []; + let pulled = arr + .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) + .filter((v, i) => !pullArr.includes(i)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); + return removed; +}; +const pullAtValue = (arr, pullArr) => { + let removed = [], + pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), + mutateTo = arr.filter((v, i) => !pullArr.includes(v)); + arr.length = 0; + mutateTo.forEach(v => arr.push(v)); + return removed; +}; +const pullBy = (arr, ...args) => { + const length = args.length; + let fn = length > 1 ? args[length - 1] : undefined; + fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; + let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); + let pulled = arr.filter((v, i) => !argState.includes(fn(v))); + arr.length = 0; + pulled.forEach(v => arr.push(v)); +}; +const radsToDegrees = rad => (rad * 180.0) / Math.PI; +const randomHexColorCode = () => { + let n = (Math.random() * 0xfffff * 1000000).toString(16); + return '#' + n.slice(0, 6); +}; +const randomIntArrayInRange = (min, max, n = 1) => + Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); +const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; +const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; + +const readFileLines = filename => + fs + .readFileSync(filename) + .toString('UTF8') + .split('\n'); +const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); +const recordAnimationFrames = (callback, autoStart = true) => { + let running = true, + raf; + const stop = () => { + running = false; + cancelAnimationFrame(raf); + }; + const start = () => { + running = true; + run(); + }; + const run = () => { + raf = requestAnimationFrame(() => { + callback(); + if (running) run(); + }); + }; + if (autoStart) start(); + return { start, stop }; +}; +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) => { + acc[key] = el[key]; + return acc; + }, {}) + ); +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 removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); +const renameKeys = (keysMap, obj) => + Object.keys(obj).reduce( + (acc, key) => ({ + ...acc, + ...{ [keysMap[key] || key]: obj[key] } + }), + {} + ); +const reverseString = str => [...str].reverse().join(''); +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 runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); +const sample = arr => arr[Math.floor(Math.random() * arr.length)]; +const sampleSize = ([...arr], n = 1) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr.slice(0, n); +}; +const scrollToTop = () => { + const c = document.documentElement.scrollTop || document.body.scrollTop; + if (c > 0) { + window.requestAnimationFrame(scrollToTop); + window.scrollTo(0, c - c / 8); + } +}; +const sdbm = str => { + let arr = str.split(''); + return arr.reduce( + (hashCode, currentVal) => + (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), + 0 + ); +}; +const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; +const serializeForm = form => + Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&'); +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 show = (...el) => [...el].forEach(e => (e.style.display = '')); +const shuffle = ([...arr]) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr; +}; +const similarity = (arr, values) => arr.filter(v => values.includes(v)); +const size = val => + Array.isArray(val) + ? val.length + : val && typeof val === 'object' + ? val.size || val.length || Object.keys(val).length + : typeof val === 'string' + ? new Blob([val]).size + : 0; +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); +const smoothScroll = element => + document.querySelector(element).scrollIntoView({ + behavior: 'smooth' + }); +const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); +const sortedIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); + return index === -1 ? arr.length : index; +}; +const sortedIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); + return index === -1 ? arr.length : index; +}; +const sortedLastIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); + return index === -1 ? 0 : arr.length - index; +}; +const sortedLastIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr + .map(fn) + .reverse() + .findIndex(el => (isDescending ? val <= el : val >= el)); + return index === -1 ? 0 : arr.length - index; +}; +const splitLines = str => str.split(/\r?\n/); const spreadOver = fn => argsArr => fn(...argsArr); -const stableSort = (arr, compare) => - arr - .map((item, index) => ({ item, index })) - .sort((a, b) => compare(a.item, b.item) || a.index - b.index) - .map(({ item }) => item); -const standardDeviation = (arr, usePopulation = false) => { - const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; - return Math.sqrt( - arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / - (arr.length - (usePopulation ? 0 : 1)) - ); -}; -const stringPermutations = str => { - if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; - return str - .split('') - .reduce( - (acc, letter, i) => - acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), - [] - ); -}; -const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); -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 symmetricDifference = (a, b) => { - const sA = new Set(a), - sB = new Set(b); - return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; -}; -const symmetricDifferenceBy = (a, b, fn) => { - const sA = new Set(a.map(v => fn(v))), - sB = new Set(b.map(v => fn(v))); - return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; -}; -const symmetricDifferenceWith = (arr, val, comp) => [ - ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), - ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) -]; -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 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 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 toCamelCase = str => { - let 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(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) - .join(''); - return s.slice(0, 1).toLowerCase() + s.slice(1); -}; -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, - (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], - ordinals = ['st', 'nd', 'rd', 'th'], - oPattern = [1, 2, 3, 4], - tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; - return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) - ? int + ordinals[digits[0] - 1] - : int + ordinals[3]; -}; -const toSafeInteger = num => - Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); -const toSnakeCase = 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 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 truncateString = (str, num) => - str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; -const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); -const unary = fn => val => fn(val); -const uncurry = (fn, n = 1) => (...args) => { - const next = acc => args => args.reduce((x, y) => x(y), acc); - if (n > args.length) throw new RangeError('Arguments too few!'); - return next(fn)(args.slice(0, n)); -}; -const unescapeHTML = str => - str.replace( - /&|<|>|'|"/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - ''': "'", - '"': '"' - }[tag] || tag) - ); -const unflattenObject = obj => - Object.keys(obj).reduce((acc, k) => { - if (k.indexOf('.') !== -1) { - const keys = k.split('.'); - Object.assign( - acc, - JSON.parse( - '{' + - keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + - obj[k] + - '}'.repeat(keys.length) - ) - ); - } else acc[k] = obj[k]; - return acc; - }, {}); -const unfold = (fn, seed) => { - let result = [], - val = [null, seed]; - while ((val = fn(val[1]))) result.push(val[0]); - 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 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)]; -const uniqueElementsBy = (arr, fn) => - arr.reduce((acc, v) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); -const uniqueElementsByRight = (arr, fn) => - arr.reduceRight((acc, v) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); -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 unzipWith = (arr, fn) => - 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 => []) - ) - .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 vectorDistance = (...coords) => { - let pointLength = Math.trunc(coords.length / 2); - let sum = coords - .slice(0, pointLength) - .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0); - return Math.sqrt(sum); -}; -const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); -const without = (arr, ...args) => arr.filter(v => !args.includes(v)); -const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); -const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); -const yesNo = (val, def = false) => - /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; -const zip = (...arrays) => { - const maxLength = Math.max(...arrays.map(x => x.length)); - return Array.from({ length: maxLength }).map((_, i) => { - return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); - }); -}; -const zipObject = (props, values) => - props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); -const zipWith = (...array) => { - const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; - return Array.from( - { length: Math.max(...array.map(a => a.length)) }, - (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])) - ); -}; - 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); +const stableSort = (arr, compare) => + arr + .map((item, index) => ({ item, index })) + .sort((a, b) => compare(a.item, b.item) || a.index - b.index) + .map(({ item }) => item); +const standardDeviation = (arr, usePopulation = false) => { + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + return Math.sqrt( + arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / + (arr.length - (usePopulation ? 0 : 1)) + ); +}; +const stringPermutations = str => { + if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; + return str + .split('') + .reduce( + (acc, letter, i) => + acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), + [] + ); +}; +const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); +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 symmetricDifference = (a, b) => { + const sA = new Set(a), + sB = new Set(b); + return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; +}; +const symmetricDifferenceBy = (a, b, fn) => { + const sA = new Set(a.map(v => fn(v))), + sB = new Set(b.map(v => fn(v))); + return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; +}; +const symmetricDifferenceWith = (arr, val, comp) => [ + ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), + ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) +]; +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 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 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 && + 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.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) + .join(''); + return s.slice(0, 1).toLowerCase() + s.slice(1); +}; +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 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 toOrdinalSuffix = num => { + const int = parseInt(num), + digits = [int % 10, int % 100], + ordinals = ['st', 'nd', 'rd', 'th'], + oPattern = [1, 2, 3, 4], + tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; + return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) + ? int + ordinals[digits[0] - 1] + : int + ordinals[3]; +}; +const toSafeInteger = num => + Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); +const toSnakeCase = 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 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 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 truncateString = (str, num) => + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; +const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); +const unary = fn => val => fn(val); +const uncurry = (fn, n = 1) => (...args) => { + const next = acc => args => args.reduce((x, y) => x(y), acc); + if (n > args.length) throw new RangeError('Arguments too few!'); + return next(fn)(args.slice(0, n)); +}; +const unescapeHTML = str => + str.replace( + /&|<|>|'|"/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + ''': "'", + '"': '"' + }[tag] || tag) + ); +const unflattenObject = obj => + Object.keys(obj).reduce((acc, k) => { + if (k.indexOf('.') !== -1) { + const keys = k.split('.'); + Object.assign( + acc, + JSON.parse( + '{' + + keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + + obj[k] + + '}'.repeat(keys.length) + ) + ); + } else acc[k] = obj[k]; + return acc; + }, {}); +const unfold = (fn, seed) => { + let result = [], + val = [null, seed]; + while ((val = fn(val[1]))) result.push(val[0]); + 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 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)]; +const uniqueElementsBy = (arr, fn) => + arr.reduce((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); +const uniqueElementsByRight = (arr, fn) => + arr.reduceRight((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); +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 unzipWith = (arr, fn) => + 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 => []) + ) + .map(val => fn(...val)); +const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; +const vectorDistance = (...coords) => { + let pointLength = Math.trunc(coords.length / 2); + let sum = coords + .slice(0, pointLength) + .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0); + return Math.sqrt(sum); +}; +const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); +const without = (arr, ...args) => arr.filter(v => !args.includes(v)); +const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); +const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); +const yesNo = (val, def = false) => + /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; +const zip = (...arrays) => { + const maxLength = Math.max(...arrays.map(x => x.length)); + return Array.from({ length: maxLength }).map((_, i) => { + return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); + }); +}; +const zipObject = (props, values) => + props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); +const zipWith = (...array) => { + const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; + return Array.from( + { length: Math.max(...array.map(a => a.length)) }, + (_, 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); -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,checkProp,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,deepGet,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,formToObject,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,serializeForm,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,vectorDistance,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 +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,checkProp,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,deepGet,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,formToObject,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,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,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,serializeForm,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,vectorDistance,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