Prepare repository for merge
This commit is contained in:
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Partial sum array
|
||||
type: snippet
|
||||
tags: [math]
|
||||
author: chalarangelo
|
||||
cover: river-house-lights
|
||||
dateModified: 2022-01-30T13:10:13+02:00
|
||||
---
|
||||
|
||||
Creates an array of partial sums.
|
||||
|
||||
- Use `Array.prototype.reduce()`, initialized with an empty array accumulator to iterate over `nums`.
|
||||
- Use `Array.prototype.slice()` to get the previous partial sum or `0` and add the current element to it.
|
||||
- Use the spread operator (`...`) to add the new partial sum to the accumulator array containing the previous sums.
|
||||
|
||||
```js
|
||||
const accumulate = (...nums) =>
|
||||
nums.reduce((acc, n) => [...acc, n + (acc.slice(-1)[0] || 0)], []);
|
||||
```
|
||||
|
||||
```js
|
||||
accumulate(1, 2, 3, 4); // [1, 3, 6, 10]
|
||||
accumulate(...[1, 2, 3, 4]); // [1, 3, 6, 10]
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Add class to HTML element
|
||||
type: snippet
|
||||
tags: [browser]
|
||||
author: chalarangelo
|
||||
cover: budapest-palace
|
||||
dateModified: 2020-12-30T19:21:15+02:00
|
||||
---
|
||||
|
||||
Adds a class to an HTML element.
|
||||
|
||||
- Use `Element.classList` and `DOMTokenList.add()` to add the specified class to the element.
|
||||
|
||||
```js
|
||||
const addClass = (el, className) => el.classList.add(className);
|
||||
```
|
||||
|
||||
```js
|
||||
addClass(document.querySelector('p'), 'special');
|
||||
// The paragraph will now have the 'special' class
|
||||
```
|
||||
@ -1,26 +0,0 @@
|
||||
---
|
||||
title: Add days to date
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: digital-nomad-12
|
||||
dateModified: 2020-11-28T19:18:29+02:00
|
||||
---
|
||||
|
||||
Calculates the date of `n` days from the given date, returning its string representation.
|
||||
|
||||
- Use the `Date` constructor to create a `Date` object from the first argument.
|
||||
- Use `Date.prototype.getDate()` and `Date.prototype.setDate()` to add `n` days to the given date.
|
||||
- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.
|
||||
|
||||
```js
|
||||
const addDaysToDate = (date, n) => {
|
||||
const d = new Date(date);
|
||||
d.setDate(d.getDate() + n);
|
||||
return d.toISOString().split('T')[0];
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
addDaysToDate('2020-10-15', 10); // '2020-10-25'
|
||||
addDaysToDate('2020-10-15', -10); // '2020-10-05'
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Add event listener to all targets
|
||||
type: snippet
|
||||
tags: [browser,event]
|
||||
author: chalarangelo
|
||||
cover: red-mountain
|
||||
dateModified: 2021-04-22T08:53:29+03:00
|
||||
---
|
||||
|
||||
Attaches an event listener to all the provided targets.
|
||||
|
||||
- Use `Array.prototype.forEach()` and `EventTarget.addEventListener()` to attach the provided `listener` for the given event `type` to all `targets`.
|
||||
|
||||
```js
|
||||
const addEventListenerAll = (targets, type, listener, options, useCapture) => {
|
||||
targets.forEach(target =>
|
||||
target.addEventListener(type, listener, options, useCapture)
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
addEventListenerAll(document.querySelectorAll('a'), 'click', () =>
|
||||
console.log('Clicked a link')
|
||||
);
|
||||
// Logs 'Clicked a link' whenever any anchor element is clicked
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Add minutes to date
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: lake-trees
|
||||
dateModified: 2020-11-28T19:27:46+02:00
|
||||
---
|
||||
|
||||
Calculates the date of `n` minutes from the given date, returning its string representation.
|
||||
|
||||
- Use the `Date` constructor to create a `Date` object from the first argument.
|
||||
- Use `Date.prototype.getTime()` and `Date.prototype.setTime()` to add `n` minutes to the given date.
|
||||
- Use `Date.prototype.toISOString()`, `String.prototype.split()` and `String.prototype.replace()` to return a string in `yyyy-mm-dd HH:MM:SS` format.
|
||||
|
||||
|
||||
```js
|
||||
const addMinutesToDate = (date, n) => {
|
||||
const d = new Date(date);
|
||||
d.setTime(d.getTime() + n * 60000);
|
||||
return d.toISOString().split('.')[0].replace('T',' ');
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
addMinutesToDate('2020-10-19 12:00:00', 10); // '2020-10-19 12:10:00'
|
||||
addMinutesToDate('2020-10-19', -10); // '2020-10-18 23:50:00'
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Add multiple listeners
|
||||
type: snippet
|
||||
tags: [browser,event]
|
||||
cover: balloons
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Adds multiple event listeners with the same handler to an element.
|
||||
|
||||
- Use `Array.prototype.forEach()` and `EventTarget.addEventListener()` to add multiple event listeners with an assigned callback function to an element.
|
||||
|
||||
```js
|
||||
const addMultipleListeners = (el, types, listener, options, useCapture) => {
|
||||
types.forEach(type =>
|
||||
el.addEventListener(type, listener, options, useCapture)
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
addMultipleListeners(
|
||||
document.querySelector('.my-element'),
|
||||
['click', 'mousedown'],
|
||||
() => { console.log('hello!') }
|
||||
);
|
||||
```
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Add styles to HTML element
|
||||
type: snippet
|
||||
tags: [browser]
|
||||
author: chalarangelo
|
||||
cover: digital-nomad-14
|
||||
dateModified: 2021-01-07T00:37:43+02:00
|
||||
---
|
||||
|
||||
Adds the provided styles to the given HTML element.
|
||||
|
||||
- Use `Object.assign()` and `HTMLElement.style` to merge the provided `styles` object into the style of the given element.
|
||||
|
||||
```js
|
||||
const addStyles = (el, styles) => Object.assign(el.style, styles);
|
||||
```
|
||||
|
||||
```js
|
||||
addStyles(document.getElementById('my-element'), {
|
||||
background: 'red',
|
||||
color: '#ffff00',
|
||||
fontSize: '3rem'
|
||||
});
|
||||
```
|
||||
@ -1,29 +0,0 @@
|
||||
---
|
||||
title: Add weekdays to date
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: digital-nomad-9
|
||||
dateModified: 2021-01-08T00:23:44+02:00
|
||||
---
|
||||
|
||||
Calculates the date after adding the given number of business days.
|
||||
|
||||
- Use `Array.from()` to construct an array with `length` equal to the `count` of business days to be added.
|
||||
- Use `Array.prototype.reduce()` to iterate over the array, starting from `startDate` and incrementing, using `Date.prototype.getDate()` and `Date.prototype.setDate()`.
|
||||
- If the current `date` is on a weekend, update it again by adding either one day or two days to make it a weekday.
|
||||
- **NOTE:** Does not take official holidays into account.
|
||||
|
||||
```js
|
||||
const addWeekDays = (startDate, count) =>
|
||||
Array.from({ length: count }).reduce(date => {
|
||||
date = new Date(date.setDate(date.getDate() + 1));
|
||||
if (date.getDay() % 6 === 0)
|
||||
date = new Date(date.setDate(date.getDate() + (date.getDay() / 6 + 1)));
|
||||
return date;
|
||||
}, startDate);
|
||||
```
|
||||
|
||||
```js
|
||||
addWeekDays(new Date('Oct 09, 2020'), 5); // 'Oct 16, 2020'
|
||||
addWeekDays(new Date('Oct 12, 2020'), 5); // 'Oct 19, 2020'
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Check if array elements are equal based on function
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: orange-coffee-2
|
||||
dateModified: 2020-10-19T22:14:49+03:00
|
||||
---
|
||||
|
||||
Checks if all elements in an array are equal, based on the provided mapping function.
|
||||
|
||||
- Apply `fn` to the first element of `arr`.
|
||||
- Use `Array.prototype.every()` to check if `fn` returns the same value for all elements in the array as it did for the first one.
|
||||
- Elements in the array are compared using the strict comparison operator, which does not account for `NaN` self-inequality.
|
||||
|
||||
```js
|
||||
const allEqualBy = (arr, fn) => {
|
||||
const eql = fn(arr[0]);
|
||||
return arr.every(val => fn(val) === eql);
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
allEqualBy([1.1, 1.2, 1.3], Math.round); // true
|
||||
allEqualBy([1.1, 1.3, 1.6], Math.round); // false
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Check if array elements are equal
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: shelf-plant
|
||||
dateModified: 2020-10-18T20:24:28+03:00
|
||||
---
|
||||
|
||||
Checks 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]);
|
||||
```
|
||||
|
||||
```js
|
||||
allEqual([1, 2, 3, 4, 5, 6]); // false
|
||||
allEqual([1, 1, 1, 1]); // true
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Check if all array elements are unique based on function
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: digital-nomad-10
|
||||
dateModified: 2021-01-08T00:23:44+02:00
|
||||
---
|
||||
|
||||
Checks if all elements in an array are unique, based on the provided mapping function.
|
||||
|
||||
- Use `Array.prototype.map()` to apply `fn` to all elements in `arr`.
|
||||
- Create a new `Set` from the mapped values to keep only unique occurrences.
|
||||
- Use `Array.prototype.length` and `Set.prototype.size` to compare the length of the unique mapped values to the original array.
|
||||
|
||||
```js
|
||||
const allUniqueBy = (arr, fn) => arr.length === new Set(arr.map(fn)).size;
|
||||
```
|
||||
|
||||
```js
|
||||
allUniqueBy([1.2, 2.4, 2.9], Math.round); // true
|
||||
allUniqueBy([1.2, 2.3, 2.4], Math.round); // false
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Check if all array elements are unique
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: jars-on-shelf
|
||||
dateModified: 2021-01-08T00:23:44+02:00
|
||||
---
|
||||
|
||||
Checks if all elements in an array are unique.
|
||||
|
||||
- Create a new `Set` from the mapped values to keep only unique occurrences.
|
||||
- Use `Array.prototype.length` and `Set.prototype.size` to compare the length of the unique values to the original array.
|
||||
|
||||
```js
|
||||
const allUnique = arr => arr.length === new Set(arr).size;
|
||||
```
|
||||
|
||||
```js
|
||||
allUnique([1, 2, 3, 4]); // true
|
||||
allUnique([1, 1, 2, 3]); // false
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Test if all array elements are truthy
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: touch-flower
|
||||
dateModified: 2020-10-18T20:24:28+03:00
|
||||
---
|
||||
|
||||
Checks if the provided predicate function returns `true` for all elements in a collection.
|
||||
|
||||
- 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);
|
||||
```
|
||||
|
||||
```js
|
||||
all([4, 2, 3], x => x > 1); // true
|
||||
all([1, 2, 3]); // true
|
||||
```
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
title: Sort array alphabetically
|
||||
type: snippet
|
||||
tags: [array]
|
||||
author: chalarangelo
|
||||
cover: boutique-home-office-1
|
||||
dateModified: 2023-02-15T05:00:00-04:00
|
||||
---
|
||||
|
||||
Sorts an array of objects alphabetically based on a given property.
|
||||
|
||||
- Use `Array.prototype.sort()` to sort the array based on the given property.
|
||||
- Use `String.prototype.localeCompare()` to compare the values for the given property.
|
||||
|
||||
```js
|
||||
const alphabetical = (arr, getter, order = 'asc') =>
|
||||
arr.sort(
|
||||
order === 'desc'
|
||||
? (a, b) => getter(b).localeCompare(getter(a))
|
||||
: (a, b) => getter(a).localeCompare(getter(b))
|
||||
);
|
||||
```
|
||||
|
||||
```js
|
||||
const people = [ { name: 'John' }, { name: 'Adam' }, { name: 'Mary' } ];
|
||||
alphabetical(people, g => g.name);
|
||||
// [ { name: 'Adam' }, { name: 'John' }, { name: 'Mary' } ]
|
||||
alphabetical(people, g => g.name, 'desc');
|
||||
// [ { name: 'Mary' }, { name: 'John' }, { name: 'Adam' } ]
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Logical and
|
||||
type: snippet
|
||||
tags: [math,logic]
|
||||
unlisted: true
|
||||
cover: succulent-1
|
||||
dateModified: 2021-01-04T13:04:15+02:00
|
||||
---
|
||||
|
||||
Checks if both arguments are `true`.
|
||||
|
||||
- Use the logical and (`&&`) operator on the two given values.
|
||||
|
||||
```js
|
||||
const and = (a, b) => a && b;
|
||||
```
|
||||
|
||||
```js
|
||||
and(true, true); // true
|
||||
and(true, false); // false
|
||||
and(false, false); // false
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Test if any array element is truthy
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: basket-paper
|
||||
dateModified: 2020-10-18T20:24:28+03:00
|
||||
---
|
||||
|
||||
Checks if the provided predicate function returns `true` for at least one element in a collection.
|
||||
|
||||
- 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);
|
||||
```
|
||||
|
||||
```js
|
||||
any([0, 1, 2, 0], x => x >= 2); // true
|
||||
any([0, 0, 1, 0]); // true
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Consecutive element subarrays
|
||||
type: snippet
|
||||
tags: [array]
|
||||
author: chalarangelo
|
||||
cover: camera-zoom
|
||||
dateModified: 2020-10-18T20:24:28+03:00
|
||||
---
|
||||
|
||||
Creates an array of `n`-tuples of consecutive elements.
|
||||
|
||||
- Use `Array.prototype.slice()` and `Array.prototype.map()` to create an array of appropriate length.
|
||||
- Populate the array with `n`-tuples of consecutive elements from `arr`.
|
||||
- If `n` is greater than the length of `arr`, return an empty array.
|
||||
|
||||
```js
|
||||
const aperture = (n, arr) =>
|
||||
n > arr.length
|
||||
? []
|
||||
: arr.slice(n - 1).map((v, i) => arr.slice(i, i + n));
|
||||
```
|
||||
|
||||
```js
|
||||
aperture(2, [1, 2, 3, 4]); // [[1, 2], [2, 3], [3, 4]]
|
||||
aperture(3, [1, 2, 3, 4]); // [[1, 2, 3], [2, 3, 4]]
|
||||
aperture(5, [1, 2, 3, 4]); // []
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Approximate number equality
|
||||
type: snippet
|
||||
tags: [math]
|
||||
cover: engine
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
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 argument, `epsilon`, to use a default value of `0.001`.
|
||||
|
||||
```js
|
||||
const approximatelyEqual = (v1, v2, epsilon = 0.001) =>
|
||||
Math.abs(v1 - v2) < epsilon;
|
||||
```
|
||||
|
||||
```js
|
||||
approximatelyEqual(Math.PI / 2.0, 1.5708); // true
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Arithmetic progression
|
||||
type: snippet
|
||||
tags: [math,algorithm]
|
||||
cover: u-got-this
|
||||
dateModified: 2021-10-13T19:29:39+02:00
|
||||
---
|
||||
|
||||
Creates an array of numbers in the arithmetic progression, starting with the given positive integer and up to the specified limit.
|
||||
|
||||
- Use `Array.from()` to create an array of the desired length, `lim / n`. Use a map function to fill it with the desired values in the given range.
|
||||
|
||||
```js
|
||||
const arithmeticProgression = (n, lim) =>
|
||||
Array.from({ length: Math.ceil(lim / n) }, (_, i) => (i + 1) * n );
|
||||
```
|
||||
|
||||
```js
|
||||
arithmeticProgression(5, 25); // [5, 10, 15, 20, 25]
|
||||
```
|
||||
@ -1,29 +0,0 @@
|
||||
---
|
||||
title: Array to CSV
|
||||
type: snippet
|
||||
tags: [array,string]
|
||||
cover: sunrise-over-city
|
||||
dateModified: 2020-11-03T21:55:08+02:00
|
||||
---
|
||||
|
||||
Converts a 2D array to a comma-separated values (CSV) string.
|
||||
|
||||
- Use `Array.prototype.map()` and `Array.prototype.join()` to combine individual 1D arrays (rows) into strings, using the provided `delimiter`.
|
||||
- Use `Array.prototype.join()` to combine all rows into a CSV string, separating each row with a newline (`\n`).
|
||||
- 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');
|
||||
```
|
||||
|
||||
```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'
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Array to HTML list
|
||||
type: snippet
|
||||
tags: [browser,array]
|
||||
cover: red-succulent
|
||||
dateModified: 2020-10-20T11:46:23+03:00
|
||||
---
|
||||
|
||||
Converts the given array elements into `<li>` tags and appends them to the list of the given id.
|
||||
|
||||
- Use `Array.prototype.map()` and `Document.querySelector()` to create a list of html tags.
|
||||
|
||||
```js
|
||||
const arrayToHTMLList = (arr, listID) =>
|
||||
document.querySelector(`#${listID}`).innerHTML += arr
|
||||
.map(item => `<li>${item}</li>`)
|
||||
.join('');
|
||||
```
|
||||
|
||||
```js
|
||||
arrayToHTMLList(['item 1', 'item 2'], 'myListID');
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Function arity
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: trippy-chemicals
|
||||
dateModified: 2020-10-18T20:24:28+03:00
|
||||
---
|
||||
|
||||
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()` and the spread operator (`...`).
|
||||
|
||||
```js
|
||||
const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
|
||||
```
|
||||
|
||||
```js
|
||||
const firstTwoMax = ary(Math.max, 2);
|
||||
[[2, 6, 'a'], [6, 4, 8], [10]].map(x => firstTwoMax(...x)); // [6, 6, 10]
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Assert object keys are valid
|
||||
type: snippet
|
||||
tags: [object]
|
||||
author: chalarangelo
|
||||
cover: river-flow
|
||||
dateModified: 2021-07-18T05:00:00-04:00
|
||||
---
|
||||
|
||||
Validates all keys in an object match the given `keys`.
|
||||
|
||||
- Use `Object.keys()` to get the keys of the given object, `obj`.
|
||||
- Use `Array.prototype.every()` and `Array.prototype.includes()` to validate that each key in the object is specified in the `keys` array.
|
||||
|
||||
```js
|
||||
const assertValidKeys = (obj, keys) =>
|
||||
Object.keys(obj).every(key => keys.includes(key));
|
||||
```
|
||||
|
||||
```js
|
||||
assertValidKeys({ id: 10, name: 'apple' }, ['id', 'name']); // true
|
||||
assertValidKeys({ id: 10, name: 'apple' }, ['id', 'type']); // false
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Decode Base64 encoded string
|
||||
type: snippet
|
||||
tags: [node,string]
|
||||
cover: thread
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
Decodes a string of data which has been encoded using base-64 encoding.
|
||||
|
||||
- Create a `Buffer` for the given string with base-64 encoding.
|
||||
- Use `Buffer.prototype.toString()` to return the decoded string.
|
||||
|
||||
```js
|
||||
const atob = str => Buffer.from(str, 'base64').toString('binary');
|
||||
```
|
||||
|
||||
```js
|
||||
atob('Zm9vYmFy'); // 'foobar'
|
||||
```
|
||||
@ -1,29 +0,0 @@
|
||||
---
|
||||
title: Attempt invoking a function
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: spanish-resort
|
||||
dateModified: 2020-10-18T20:24:28+03:00
|
||||
---
|
||||
|
||||
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.
|
||||
- If the caught object is not an `Error`, use it to create a new `Error`.
|
||||
|
||||
```js
|
||||
const attempt = (fn, ...args) => {
|
||||
try {
|
||||
return fn(...args);
|
||||
} catch (e) {
|
||||
return e instanceof Error ? e : new Error(e);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
var elements = attempt(function(selector) {
|
||||
return document.querySelectorAll(selector);
|
||||
}, '>_>');
|
||||
if (elements instanceof Error) elements = []; // elements = []
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Mapped array average
|
||||
type: snippet
|
||||
tags: [math]
|
||||
cover: rock-climbing
|
||||
dateModified: 2020-10-21T21:17:45+03:00
|
||||
---
|
||||
|
||||
Calculates 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`.
|
||||
- Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`.
|
||||
- Divide the resulting array by its length.
|
||||
|
||||
```js
|
||||
const averageBy = (arr, fn) =>
|
||||
arr
|
||||
.map(typeof fn === 'function' ? fn : val => val[fn])
|
||||
.reduce((acc, val) => acc + val, 0) / arr.length;
|
||||
```
|
||||
|
||||
```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
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Average of numbers
|
||||
type: snippet
|
||||
tags: [math]
|
||||
cover: interior-8
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Calculates 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 the resulting array by its length.
|
||||
|
||||
```js
|
||||
const average = (...nums) =>
|
||||
nums.reduce((acc, val) => acc + val, 0) / nums.length;
|
||||
```
|
||||
|
||||
```js
|
||||
average(...[1, 2, 3]); // 2
|
||||
average(1, 2, 3); // 2
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Bifurcate array based on function
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: canoe
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Splits values into two groups, based on the result of the given filtering function.
|
||||
|
||||
- Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on the value returned by `fn` for each element.
|
||||
- If `fn` returns a truthy value for any element, add it to the first group, otherwise add it to the second group.
|
||||
|
||||
```js
|
||||
const bifurcateBy = (arr, fn) =>
|
||||
arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [
|
||||
[],
|
||||
[],
|
||||
]);
|
||||
```
|
||||
|
||||
```js
|
||||
bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b');
|
||||
// [ ['beep', 'boop', 'bar'], ['foo'] ]
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Bifurcate array based on values
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: two-cities
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Splits values into two groups, based on the result of the given `filter` array.
|
||||
|
||||
- Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on `filter`.
|
||||
- If `filter` has a truthy value for any element, add it to the first group, otherwise add it to the second group.
|
||||
|
||||
```js
|
||||
const bifurcate = (arr, filter) =>
|
||||
arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [
|
||||
[],
|
||||
[],
|
||||
]);
|
||||
```
|
||||
|
||||
```js
|
||||
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]);
|
||||
// [ ['beep', 'boop', 'bar'], ['foo'] ]
|
||||
```
|
||||
@ -1,36 +0,0 @@
|
||||
---
|
||||
title: Binary search
|
||||
type: snippet
|
||||
tags: [algorithm,array]
|
||||
author: chalarangelo
|
||||
cover: zen-indoors
|
||||
dateModified: 2020-12-29T13:06:47+02:00
|
||||
---
|
||||
|
||||
Finds the index of a given element in a sorted array using the binary search algorithm.
|
||||
|
||||
- Declare the left and right search boundaries, `l` and `r`, initialized to `0` and the `length` of the array respectively.
|
||||
- Use a `while` loop to repeatedly narrow down the search subarray, using `Math.floor()` to cut it in half.
|
||||
- Return the index of the element if found, otherwise return `-1`.
|
||||
- **Note:** Does not account for duplicate values in the array.
|
||||
|
||||
```js
|
||||
const binarySearch = (arr, item) => {
|
||||
let l = 0,
|
||||
r = arr.length - 1;
|
||||
while (l <= r) {
|
||||
const mid = Math.floor((l + r) / 2);
|
||||
const guess = arr[mid];
|
||||
if (guess === item) return mid;
|
||||
if (guess > item) r = mid - 1;
|
||||
else l = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
binarySearch([1, 2, 3, 4, 5], 1); // 0
|
||||
binarySearch([1, 2, 3, 4, 5], 5); // 4
|
||||
binarySearch([1, 2, 3, 4, 5], 6); // -1
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Binary function arity
|
||||
type: snippet
|
||||
tags: [function]
|
||||
author: chalarangelo
|
||||
cover: blue-bird
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
Creates a function that accepts up to two arguments, ignoring any additional arguments.
|
||||
|
||||
- Call the provided function, `fn`, with the first two arguments given.
|
||||
|
||||
```js
|
||||
const binary = fn => (a, b) => fn(a, b);
|
||||
```
|
||||
|
||||
```js
|
||||
['2', '1', '0'].map(binary(Math.max)); // [2, 1, 2]
|
||||
```
|
||||
@ -1,36 +0,0 @@
|
||||
---
|
||||
title: Bind all object methods
|
||||
type: snippet
|
||||
tags: [object,function]
|
||||
cover: laptop-with-code
|
||||
dateModified: 2020-11-03T22:11:18+02:00
|
||||
---
|
||||
|
||||
Binds methods of an object to the object itself, overwriting the existing method.
|
||||
|
||||
- Use `Array.prototype.forEach()` to iterate over the given `fns`.
|
||||
- Return a function for each one, using `Function.prototype.apply()` to apply the given context (`obj`) to `fn`.
|
||||
|
||||
```js
|
||||
const bindAll = (obj, ...fns) =>
|
||||
fns.forEach(
|
||||
fn => (
|
||||
(f = obj[fn]),
|
||||
(obj[fn] = function() {
|
||||
return f.apply(obj);
|
||||
})
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```js
|
||||
var view = {
|
||||
label: 'docs',
|
||||
click: function() {
|
||||
console.log('clicked ' + this.label);
|
||||
}
|
||||
};
|
||||
bindAll(view, 'click');
|
||||
document.body.addEventListener('click', view.click);
|
||||
// Log 'clicked docs' when clicked.
|
||||
```
|
||||
@ -1,29 +0,0 @@
|
||||
---
|
||||
title: Bind object method
|
||||
type: snippet
|
||||
tags: [function,object]
|
||||
cover: oven-paddle
|
||||
excerpt: Creates a function that invokes a method at a key in an object, with optional additional parameters.
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
Creates a function that invokes the method at a given key of an object, optionally prepending any additional supplied parameters to 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]);
|
||||
```
|
||||
|
||||
```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!'
|
||||
```
|
||||
@ -1,26 +0,0 @@
|
||||
---
|
||||
title: Bind function context
|
||||
type: snippet
|
||||
tags: [function,object]
|
||||
cover: tranquility
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
Creates a function that invokes `fn` with a given context, optionally prepending any additional supplied parameters to the arguments.
|
||||
|
||||
- Return a `function` that uses `Function.prototype.apply()` to apply the given `context` to `fn`.
|
||||
- Use the spread operator (`...`) to prepend any additional supplied parameters to the arguments.
|
||||
|
||||
```js
|
||||
const bind = (fn, context, ...boundArgs) => (...args) =>
|
||||
fn.apply(context, [...boundArgs, ...args]);
|
||||
```
|
||||
|
||||
```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!'
|
||||
```
|
||||
@ -1,32 +0,0 @@
|
||||
---
|
||||
title: Binomial coefficient
|
||||
type: snippet
|
||||
tags: [math,algorithm]
|
||||
cover: blue-red-mountain
|
||||
dateModified: 2020-12-28T13:49:24+02:00
|
||||
---
|
||||
|
||||
Calculates the number of ways to choose `k` items from `n` items without repetition and without order.
|
||||
|
||||
- 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);
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
binomialCoefficient(8, 2); // 28
|
||||
```
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Logical and for functions
|
||||
type: snippet
|
||||
tags: [function,logic]
|
||||
unlisted: true
|
||||
cover: succulent-2
|
||||
dateModified: 2021-01-04T13:04:15+02:00
|
||||
---
|
||||
|
||||
Checks if both of the given functions return `true` for a given set of arguments.
|
||||
|
||||
- Use the logical and (`&&`) operator on the result of calling the two functions with the supplied `args`.
|
||||
|
||||
```js
|
||||
const both = (f, g) => (...args) => f(...args) && g(...args);
|
||||
```
|
||||
|
||||
```js
|
||||
const isEven = num => num % 2 === 0;
|
||||
const isPositive = num => num > 0;
|
||||
const isPositiveEven = both(isEven, isPositive);
|
||||
isPositiveEven(4); // true
|
||||
isPositiveEven(-2); // false
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Check if bottom of page is visible
|
||||
type: snippet
|
||||
tags: [browser]
|
||||
cover: red-mountain
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Checks if the bottom of the page is visible.
|
||||
|
||||
- Use `Window.scrollY`, `Element.scrollHeight` and `Element.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);
|
||||
```
|
||||
|
||||
```js
|
||||
bottomVisible(); // true
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Encode string to Base64
|
||||
type: snippet
|
||||
tags: [node,string]
|
||||
cover: laptop-journey
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
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.
|
||||
- Use `Buffer.prototype.toString()` to return the base-64 encoded string.
|
||||
|
||||
```js
|
||||
const btoa = str => Buffer.from(str, 'binary').toString('base64');
|
||||
```
|
||||
|
||||
```js
|
||||
btoa('foobar'); // 'Zm9vYmFy'
|
||||
```
|
||||
@ -1,37 +0,0 @@
|
||||
---
|
||||
title: Bubble sort
|
||||
type: snippet
|
||||
tags: [algorithm,array]
|
||||
cover: budapest-palace
|
||||
dateModified: 2020-12-29T12:18:58+02:00
|
||||
---
|
||||
|
||||
Sorts an array of numbers, using the bubble sort algorithm.
|
||||
|
||||
- Declare a variable, `swapped`, that indicates if any values were swapped during the current iteration.
|
||||
- Use the spread operator (`...`) to clone the original array, `arr`.
|
||||
- Use a `for` loop to iterate over the elements of the cloned array, terminating before the last element.
|
||||
- Use a nested `for` loop to iterate over the segment of the array between `0` and `i`, swapping any adjacent out of order elements and setting `swapped` to `true`.
|
||||
- If `swapped` is `false` after an iteration, no more changes are needed, so the cloned array is returned.
|
||||
|
||||
```js
|
||||
const bubbleSort = arr => {
|
||||
let swapped = false;
|
||||
const a = [...arr];
|
||||
for (let i = 1; i < a.length; i++) {
|
||||
swapped = false;
|
||||
for (let j = 0; j < a.length - i; j++) {
|
||||
if (a[j + 1] < a[j]) {
|
||||
[a[j], a[j + 1]] = [a[j + 1], a[j]];
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
if (!swapped) return a;
|
||||
}
|
||||
return a;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
bubbleSort([2, 1, 4, 3]); // [1, 2, 3, 4]
|
||||
```
|
||||
@ -1,33 +0,0 @@
|
||||
---
|
||||
title: Bucket sort
|
||||
type: snippet
|
||||
tags: [algorithm,array]
|
||||
cover: canoe
|
||||
dateModified: 2020-12-29T12:22:44+02:00
|
||||
---
|
||||
|
||||
Sorts an array of numbers, using the bucket sort algorithm.
|
||||
|
||||
- Use `Math.min()`, `Math.max()` and the spread operator (`...`) to find the minimum and maximum values of the given array.
|
||||
- Use `Array.from()` and `Math.floor()` to create the appropriate number of `buckets` (empty arrays).
|
||||
- Use `Array.prototype.forEach()` to populate each bucket with the appropriate elements from the array.
|
||||
- Use `Array.prototype.reduce()`, the spread operator (`...`) and `Array.prototype.sort()` to sort each bucket and append it to the result.
|
||||
|
||||
```js
|
||||
const bucketSort = (arr, size = 5) => {
|
||||
const min = Math.min(...arr);
|
||||
const max = Math.max(...arr);
|
||||
const buckets = Array.from(
|
||||
{ length: Math.floor((max - min) / size) + 1 },
|
||||
() => []
|
||||
);
|
||||
arr.forEach(val => {
|
||||
buckets[Math.floor((val - min) / size)].push(val);
|
||||
});
|
||||
return buckets.reduce((acc, b) => [...acc, ...b.sort((a, b) => a - b)], []);
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
bucketSort([6, 3, 4, 1]); // [1, 3, 4, 6]
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Byte size of string
|
||||
type: snippet
|
||||
tags: [string]
|
||||
cover: mountain-lake-cottage-2
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
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).
|
||||
- Use `Blob.size` to get the length of the string in bytes.
|
||||
|
||||
```js
|
||||
const byteSize = str => new Blob([str]).size;
|
||||
```
|
||||
|
||||
```js
|
||||
byteSize('😀'); // 4
|
||||
byteSize('Hello World'); // 11
|
||||
```
|
||||
@ -1,37 +0,0 @@
|
||||
---
|
||||
title: Caesar cipher
|
||||
type: snippet
|
||||
tags: [algorithm,string]
|
||||
cover: ancient-greek-building
|
||||
dateModified: 2020-12-29T12:29:21+02:00
|
||||
---
|
||||
|
||||
Encrypts or decrypts a given string using the Caesar cipher.
|
||||
|
||||
- Use the modulo (`%`) operator and the ternary operator (`?`) to calculate the correct encryption/decryption key.
|
||||
- Use the spread operator (`...`) and `Array.prototype.map()` to iterate over the letters of the given string.
|
||||
- Use `String.prototype.charCodeAt()` and `String.fromCharCode()` to convert each letter appropriately, ignoring special characters, spaces etc.
|
||||
- Use `Array.prototype.join()` to combine all the letters into a string.
|
||||
- Pass `true` to the last parameter, `decrypt`, to decrypt an encrypted string.
|
||||
|
||||
```js
|
||||
const caesarCipher = (str, shift, decrypt = false) => {
|
||||
const s = decrypt ? (26 - shift) % 26 : shift;
|
||||
const n = s > 0 ? s : 26 + (s % 26);
|
||||
return [...str]
|
||||
.map((l, i) => {
|
||||
const c = str.charCodeAt(i);
|
||||
if (c >= 65 && c <= 90)
|
||||
return String.fromCharCode(((c - 65 + n) % 26) + 65);
|
||||
if (c >= 97 && c <= 122)
|
||||
return String.fromCharCode(((c - 97 + n) % 26) + 97);
|
||||
return l;
|
||||
})
|
||||
.join('');
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
caesarCipher('Hello World!', -3); // 'Ebiil Tloia!'
|
||||
caesarCipher('Ebiil Tloia!', 23, true); // 'Hello World!'
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Call or return
|
||||
type: snippet
|
||||
tags: [function]
|
||||
author: chalarangelo
|
||||
cover: cows
|
||||
dateModified: 2022-04-04T05:00:00-04:00
|
||||
---
|
||||
|
||||
Calls the argument if it's a function, otherwise returns it.
|
||||
|
||||
- Use the `typeof` operator to check if the given argument is a function.
|
||||
- If it is, use the spread operator (`...`) to call it with the rest of the given arguments. Otherwise, return it.
|
||||
|
||||
```js
|
||||
const callOrReturn = (fn, ...args) =>
|
||||
typeof fn === 'function' ? fn(...args) : fn;
|
||||
```
|
||||
|
||||
```js
|
||||
callOrReturn(x => x + 1, 1); // 2
|
||||
callOrReturn(1, 1); // 1
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Call functions with context
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: rabbit-call
|
||||
dateModified: 2021-06-13T13:50:25+03:00
|
||||
---
|
||||
|
||||
Given a key and a set of arguments, call them when given a context.
|
||||
|
||||
- Use a closure to call `key` with `args` for the given `context`.
|
||||
|
||||
```js
|
||||
const call = (key, ...args) => context => context[key](...args);
|
||||
```
|
||||
|
||||
```js
|
||||
Promise.resolve([1, 2, 3])
|
||||
.then(call('map', x => 2 * x))
|
||||
.then(console.log); // [ 2, 4, 6 ]
|
||||
const map = call.bind(null, 'map');
|
||||
Promise.resolve([1, 2, 3])
|
||||
.then(map(x => 2 * x))
|
||||
.then(console.log); // [ 2, 4, 6 ]
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Capitalize every word
|
||||
type: snippet
|
||||
tags: [string,regexp]
|
||||
cover: laptop-plants
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
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());
|
||||
```
|
||||
|
||||
```js
|
||||
capitalizeEveryWord('hello world!'); // 'Hello World!'
|
||||
```
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Capitalize string
|
||||
type: snippet
|
||||
tags: [string]
|
||||
cover: digital-nomad-3
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Capitalizes the first letter of a string.
|
||||
|
||||
- Use array destructuring and `String.prototype.toUpperCase()` to capitalize the first letter of the string.
|
||||
- Use `Array.prototype.join()` to combine the capitalized `first` with the `...rest` of the characters.
|
||||
- Omit the `lowerRest` argument 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(''));
|
||||
```
|
||||
|
||||
```js
|
||||
capitalize('fooBar'); // 'FooBar'
|
||||
capitalize('fooBar', true); // 'Foobar'
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Cartesian product
|
||||
type: snippet
|
||||
tags: [math]
|
||||
cover: sail-away
|
||||
dateModified: 2020-12-29T12:31:43+02:00
|
||||
---
|
||||
|
||||
Calculates the cartesian product of two arrays.
|
||||
|
||||
- Use `Array.prototype.reduce()`, `Array.prototype.map()` and the spread operator (`...`) to generate all possible element pairs from the two arrays.
|
||||
|
||||
```js
|
||||
const cartesianProduct = (a, b) =>
|
||||
a.reduce((p, x) => [...p, ...b.map(y => [x, y])], []);
|
||||
```
|
||||
|
||||
```js
|
||||
cartesianProduct(['x', 'y'], [1, 2]);
|
||||
// [['x', 1], ['x', 2], ['y', 1], ['y', 2]]
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Cast to array
|
||||
type: snippet
|
||||
tags: [type,array]
|
||||
cover: man-red-sunset
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
Casts the provided value as an array if it's not one.
|
||||
|
||||
- Use `Array.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]);
|
||||
```
|
||||
|
||||
```js
|
||||
castArray('foo'); // ['foo']
|
||||
castArray([1]); // [1]
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Celsius to Fahrenheit
|
||||
type: snippet
|
||||
tags: [math]
|
||||
unlisted: true
|
||||
cover: last-light
|
||||
dateModified: 2021-01-04T13:04:15+02:00
|
||||
---
|
||||
|
||||
Converts Celsius to Fahrenheit.
|
||||
|
||||
- Follow the conversion formula `F = 1.8 * C + 32`.
|
||||
|
||||
```js
|
||||
const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;
|
||||
```
|
||||
|
||||
```js
|
||||
celsiusToFahrenheit(33); // 91.4
|
||||
```
|
||||
@ -1,39 +0,0 @@
|
||||
---
|
||||
title: Chain async functions
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: tram-car
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
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();
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
chainAsync([
|
||||
next => {
|
||||
console.log('0 seconds');
|
||||
setTimeout(next, 1000);
|
||||
},
|
||||
next => {
|
||||
console.log('1 second');
|
||||
setTimeout(next, 1000);
|
||||
},
|
||||
() => {
|
||||
console.log('2 second');
|
||||
}
|
||||
]);
|
||||
```
|
||||
@ -1,32 +0,0 @@
|
||||
---
|
||||
title: Change color lightness
|
||||
type: snippet
|
||||
tags: [string,browser,regexp]
|
||||
cover: aerial-view-port
|
||||
dateModified: 2020-10-31T16:37:54+02:00
|
||||
---
|
||||
|
||||
Changes the lightness value of an `hsl()` color string.
|
||||
|
||||
- Use `String.prototype.match()` to get an array of 3 strings with the numeric values.
|
||||
- Use `Array.prototype.map()` in combination with `Number` to convert them into an array of numeric values.
|
||||
- Make sure the lightness is within the valid range (between `0` and `100`), using `Math.max()` and `Math.min()`.
|
||||
- Use a template literal to create a new `hsl()` string with the updated value.
|
||||
|
||||
```js
|
||||
const changeLightness = (delta, hslStr) => {
|
||||
const [hue, saturation, lightness] = hslStr.match(/\d+/g).map(Number);
|
||||
|
||||
const newLightness = Math.max(
|
||||
0,
|
||||
Math.min(100, lightness + parseFloat(delta))
|
||||
);
|
||||
|
||||
return `hsl(${hue}, ${saturation}%, ${newLightness}%)`;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
changeLightness(10, 'hsl(330, 50%, 50%)'); // 'hsl(330, 50%, 60%)'
|
||||
changeLightness(-10, 'hsl(330, 50%, 50%)'); // 'hsl(330, 50%, 40%)'
|
||||
```
|
||||
@ -1,35 +0,0 @@
|
||||
---
|
||||
title: Check property
|
||||
type: snippet
|
||||
tags: [function,object]
|
||||
cover: white-tablet-2
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Creates a function that will invoke a predicate function for the specified property on a given object.
|
||||
|
||||
- Return a curried function, that will invoke `predicate` for the specified `prop` on `obj` and return a boolean.
|
||||
|
||||
```js
|
||||
const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]);
|
||||
```
|
||||
|
||||
```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 = checkProp(u => u.active && !u.disabled, 'user');
|
||||
|
||||
validUserSession(session); // false
|
||||
|
||||
session.user.active = true;
|
||||
validUserSession(session); // true
|
||||
|
||||
const noLength = checkProp(l => l === undefined, 'length');
|
||||
noLength([]); // false
|
||||
noLength({}); // true
|
||||
noLength(new Set()); // true
|
||||
```
|
||||
@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Split array into n chunks
|
||||
type: snippet
|
||||
tags: [array]
|
||||
author: chalarangelo
|
||||
cover: dark-leaves-2
|
||||
dateModified: 2020-11-03T21:46:13+02:00
|
||||
---
|
||||
|
||||
Chunks an array into `n` smaller arrays.
|
||||
|
||||
- Use `Math.ceil()` and `Array.prototype.length` to get the size of each chunk.
|
||||
- Use `Array.from()` to create a new array of size `n`.
|
||||
- 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 chunkIntoN = (arr, n) => {
|
||||
const size = Math.ceil(arr.length / n);
|
||||
return Array.from({ length: n }, (v, i) =>
|
||||
arr.slice(i * size, i * size + size)
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
chunkIntoN([1, 2, 3, 4, 5, 6, 7], 4); // [[1, 2], [3, 4], [5, 6], [7]]
|
||||
```
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Split into chunks
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: filter-coffee-pot
|
||||
dateModified: 2020-11-03T21:35:12+02:00
|
||||
---
|
||||
|
||||
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)
|
||||
);
|
||||
```
|
||||
|
||||
```js
|
||||
chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
|
||||
```
|
||||
@ -1,33 +0,0 @@
|
||||
---
|
||||
title: Chunk iterable
|
||||
type: snippet
|
||||
tags: [function,generator,array]
|
||||
author: chalarangelo
|
||||
cover: cave-view
|
||||
dateModified: 2021-03-16T22:50:40+02:00
|
||||
---
|
||||
|
||||
Chunks an iterable into smaller arrays of a specified size.
|
||||
|
||||
- Use a `for...of` loop over the given iterable, using `Array.prototype.push()` to add each new value to the current `chunk`.
|
||||
- Use `Array.prototype.length` to check if the current `chunk` is of the desired `size` and `yield` the value if it is.
|
||||
- Finally, use `Array.prototype.length` to check the final `chunk` and `yield` it if it's non-empty.
|
||||
|
||||
```js
|
||||
const chunkify = function* (itr, size) {
|
||||
let chunk = [];
|
||||
for (const v of itr) {
|
||||
chunk.push(v);
|
||||
if (chunk.length === size) {
|
||||
yield chunk;
|
||||
chunk = [];
|
||||
}
|
||||
}
|
||||
if (chunk.length) yield chunk;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
const x = new Set([1, 2, 1, 3, 4, 1, 2, 5]);
|
||||
[...chunkify(x, 2)]; // [[1, 2], [3, 4], [5]]
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Clamp number
|
||||
type: snippet
|
||||
tags: [math]
|
||||
cover: clay-pot-horizon
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
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));
|
||||
```
|
||||
|
||||
```js
|
||||
clampNumber(2, 3, 5); // 3
|
||||
clampNumber(1, -1, -5); // -1
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Clone RegExp
|
||||
type: snippet
|
||||
tags: [type]
|
||||
cover: tomatoes
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Clones a regular expression.
|
||||
|
||||
- Use the `RegExp` constructor, `RegExp.prototype.source` and `RegExp.prototype.flags` to clone the given regular expression.
|
||||
|
||||
```js
|
||||
const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
|
||||
```
|
||||
|
||||
```js
|
||||
const regExp = /lorem ipsum/gi;
|
||||
const regExp2 = cloneRegExp(regExp); // regExp !== regExp2
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Closest numeric match
|
||||
type: snippet
|
||||
tags: [math]
|
||||
author: chalarangelo
|
||||
cover: sparkles
|
||||
dateModified: 2022-03-30T05:00:00-04:00
|
||||
---
|
||||
|
||||
Finds the closest number from an array.
|
||||
|
||||
- Use `Array.prototype.reduce()` to scan all elements of the array.
|
||||
- Use `Math.abs()` to compare each element's distance from the target value, storing the closest match.
|
||||
|
||||
```js
|
||||
const closest = (arr, n) =>
|
||||
arr.reduce((acc, num) => (Math.abs(num - n) < Math.abs(acc - n) ? num : acc));
|
||||
```
|
||||
|
||||
```js
|
||||
closest([6, 1, 3, 7, 9], 5); // 6
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Argument coalescing factory
|
||||
type: snippet
|
||||
tags: [function,type]
|
||||
cover: coffee-phone-tray
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Customizes a coalesce function that returns the first argument which is `true` based on the given validator.
|
||||
|
||||
- Use `Array.prototype.find()` to return the first argument that returns `true` from the provided argument validation function, `valid`.
|
||||
|
||||
```js
|
||||
const coalesceFactory = valid => (...args) => args.find(valid);
|
||||
```
|
||||
|
||||
```js
|
||||
const customCoalesce = coalesceFactory(
|
||||
v => ![null, undefined, '', NaN].includes(v)
|
||||
);
|
||||
customCoalesce(undefined, null, NaN, '', 'Waldo'); // 'Waldo'
|
||||
```
|
||||
@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Argument coalescing
|
||||
type: snippet
|
||||
tags: [type]
|
||||
cover: flower-portrait-1
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
Returns the first defined, non-null argument.
|
||||
|
||||
- Use `Array.prototype.find()` and `Array.prototype.includes()` to find the first value that is not equal to `undefined` or `null`.
|
||||
|
||||
```js
|
||||
const coalesce = (...args) => args.find(v => ![undefined, null].includes(v));
|
||||
```
|
||||
|
||||
```js
|
||||
coalesce(null, undefined, '', NaN, 'Waldo'); // ''
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Convert function to variadic
|
||||
type: snippet
|
||||
tags: [function,array]
|
||||
cover: polar-bear
|
||||
dateModified: 2021-06-13T13:50:25+03:00
|
||||
---
|
||||
|
||||
Changes a function that accepts an array into a variadic function.
|
||||
|
||||
- Given a function, return a closure that collects all inputs into an array-accepting function.
|
||||
|
||||
```js
|
||||
const collectInto = fn => (...args) => fn(args);
|
||||
```
|
||||
|
||||
```js
|
||||
const Pall = collectInto(Promise.all.bind(Promise));
|
||||
let p1 = Promise.resolve(1);
|
||||
let p2 = Promise.resolve(2);
|
||||
let p3 = new Promise(resolve => setTimeout(resolve, 2000, 3));
|
||||
Pall(p1, p2, p3).then(console.log); // [1, 2, 3] (after about 2 seconds)
|
||||
```
|
||||
@ -1,40 +0,0 @@
|
||||
---
|
||||
title: Colorize text
|
||||
type: snippet
|
||||
tags: [node,string]
|
||||
cover: sea-view
|
||||
dateModified: 2020-11-03T22:11:18+02:00
|
||||
---
|
||||
|
||||
Adds 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`
|
||||
});
|
||||
```
|
||||
|
||||
```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)
|
||||
```
|
||||
@ -1,44 +0,0 @@
|
||||
---
|
||||
title: Combine object arrays
|
||||
type: snippet
|
||||
tags: [array,object]
|
||||
author: chalarangelo
|
||||
cover: digital-nomad-6
|
||||
dateModified: 2020-10-08T02:22:39+03:00
|
||||
---
|
||||
|
||||
Combines two arrays of objects, using the specified key to match objects.
|
||||
|
||||
- Use `Array.prototype.reduce()` with an object accumulator to combine all objects in both arrays based on the given `prop`.
|
||||
- Use `Object.values()` to convert the resulting object to an array and return it.
|
||||
|
||||
```js
|
||||
const combine = (a, b, prop) =>
|
||||
Object.values(
|
||||
[...a, ...b].reduce((acc, v) => {
|
||||
if (v[prop])
|
||||
acc[v[prop]] = acc[v[prop]]
|
||||
? { ...acc[v[prop]], ...v }
|
||||
: { ...v };
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
```
|
||||
|
||||
```js
|
||||
const x = [
|
||||
{ id: 1, name: 'John' },
|
||||
{ id: 2, name: 'Maria' }
|
||||
];
|
||||
const y = [
|
||||
{ id: 1, age: 28 },
|
||||
{ id: 3, age: 26 },
|
||||
{ age: 3}
|
||||
];
|
||||
combine(x, y, 'id');
|
||||
// [
|
||||
// { id: 1, name: 'John', age: 28 },
|
||||
// { id: 2, name: 'Maria' },
|
||||
// { id: 3, age: 26 }
|
||||
// ]
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Common keys
|
||||
type: snippet
|
||||
tags: [object]
|
||||
author: chalarangelo
|
||||
cover: symmetry-cloudy-mountain
|
||||
dateModified: 2022-04-23T05:00:00-04:00
|
||||
---
|
||||
|
||||
Finds the common keys between two objects.
|
||||
|
||||
- Use `Object.keys()` to get the keys of the first object.
|
||||
- Use `Object.prototype.hasOwnProperty()` to check if the second object has a key that's in the first object.
|
||||
- Use `Array.prototype.filter()` to filter out keys that aren't in both objects.
|
||||
|
||||
```js
|
||||
const commonKeys = (obj1, obj2) =>
|
||||
Object.keys(obj1).filter(key => obj2.hasOwnProperty(key));
|
||||
```
|
||||
|
||||
```js
|
||||
commonKeys({ a: 1, b: 2 }, { a: 2, c: 1 }); // ['a']
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Compact and join array
|
||||
type: snippet
|
||||
tags: [array]
|
||||
author: chalarangelo
|
||||
cover: racoon
|
||||
dateModified: 2022-04-08T05:00:00-04:00
|
||||
---
|
||||
|
||||
Removes falsy values from an array and combines the remaining values into a string.
|
||||
|
||||
- Use `Array.prototype.filter()` to filter out falsy values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`).
|
||||
- Use `Array.prototype.join()` to join the remaining values into a string.
|
||||
|
||||
```js
|
||||
const compactJoin = (arr, delim = ',') => arr.filter(Boolean).join(delim);
|
||||
```
|
||||
|
||||
```js
|
||||
compactJoin(['a', '', 'b', 'c']); // 'a,b,c'
|
||||
```
|
||||
@ -1,46 +0,0 @@
|
||||
---
|
||||
title: Compact object
|
||||
type: snippet
|
||||
tags: [object,array,recursion]
|
||||
cover: shapes
|
||||
dateModified: 2020-11-27T13:57:41+02:00
|
||||
---
|
||||
|
||||
Deeply removes all falsy values from an object or array.
|
||||
|
||||
- Use recursion.
|
||||
- Initialize the iterable data, using `Array.isArray()`, `Array.prototype.filter()` and `Boolean` for arrays in order to avoid sparse arrays.
|
||||
- Use `Object.keys()` and `Array.prototype.reduce()` to iterate over each key with an appropriate initial value.
|
||||
- Use `Boolean` to determine the truthiness of each key's value and add it to the accumulator if it's truthy.
|
||||
- Use `typeof` to determine if a given value is an `object` and call the function again to deeply compact it.
|
||||
|
||||
```js
|
||||
const compactObject = val => {
|
||||
const data = Array.isArray(val) ? val.filter(Boolean) : val;
|
||||
return Object.keys(data).reduce(
|
||||
(acc, key) => {
|
||||
const value = data[key];
|
||||
if (Boolean(value))
|
||||
acc[key] = typeof value === 'object' ? compactObject(value) : value;
|
||||
return acc;
|
||||
},
|
||||
Array.isArray(val) ? [] : {}
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
const obj = {
|
||||
a: null,
|
||||
b: false,
|
||||
c: true,
|
||||
d: 0,
|
||||
e: 1,
|
||||
f: '',
|
||||
g: 'a',
|
||||
h: [null, false, '', true, 1, 'a'],
|
||||
i: { j: 0, k: false, l: 'a' }
|
||||
};
|
||||
compactObject(obj);
|
||||
// { c: true, e: 1, g: 'a', h: [ true, 1, 'a' ], i: { l: 'a' } }
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Compact whitespaces
|
||||
type: snippet
|
||||
tags: [string,regexp]
|
||||
cover: travel-mug-1
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
Compacts whitespaces in a string.
|
||||
|
||||
- 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, ' ');
|
||||
```
|
||||
|
||||
```js
|
||||
compactWhitespace('Lorem Ipsum'); // 'Lorem Ipsum'
|
||||
compactWhitespace('Lorem \n Ipsum'); // 'Lorem Ipsum'
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Compact array
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: basket-paper
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Removes falsy values from an array.
|
||||
|
||||
- Use `Array.prototype.filter()` to filter out falsy values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`).
|
||||
|
||||
```js
|
||||
const compact = arr => arr.filter(Boolean);
|
||||
```
|
||||
|
||||
```js
|
||||
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]);
|
||||
// [ 1, 2, 3, 'a', 's', 34 ]
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Logical complement
|
||||
type: snippet
|
||||
tags: [function,logic]
|
||||
cover: flower-portrait-10
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
Returns a function that is the logical complement of the given function, `fn`.
|
||||
|
||||
- Use the logical not (`!`) operator on the result of calling `fn` with any supplied `args`.
|
||||
|
||||
```js
|
||||
const complement = fn => (...args) => !fn(...args);
|
||||
```
|
||||
|
||||
```js
|
||||
const isEven = num => num % 2 === 0;
|
||||
const isOdd = complement(isEven);
|
||||
isOdd(2); // false
|
||||
isOdd(3); // true
|
||||
```
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Reverse compose functions
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: rocky-beach
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
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)));
|
||||
```
|
||||
|
||||
```js
|
||||
const add = (x, y) => x + y;
|
||||
const square = x => x * x;
|
||||
const addAndSquare = composeRight(add, square);
|
||||
addAndSquare(1, 2); // 9
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Compose functions
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: digital-nomad-16
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
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)));
|
||||
```
|
||||
|
||||
```js
|
||||
const add5 = x => x + 5;
|
||||
const multiply = (x, y) => x * y;
|
||||
const multiplyAndAdd5 = compose(
|
||||
add5,
|
||||
multiply
|
||||
);
|
||||
multiplyAndAdd5(5, 2); // 15
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Check if string contains whitespace
|
||||
type: snippet
|
||||
tags: [string,regexp]
|
||||
author: chalarangelo
|
||||
cover: bag-waiting
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
Checks if the given string contains any whitespace characters.
|
||||
|
||||
- Use `RegExp.prototype.test()` with an appropriate regular expression to check if the given string contains any whitespace characters.
|
||||
|
||||
```js
|
||||
const containsWhitespace = str => /\s/.test(str);
|
||||
```
|
||||
|
||||
```js
|
||||
containsWhitespace('lorem'); // false
|
||||
containsWhitespace('lorem ipsum'); // true
|
||||
```
|
||||
@ -1,26 +0,0 @@
|
||||
---
|
||||
title: Converge branching functions
|
||||
type: snippet
|
||||
tags: [function]
|
||||
excerpt: Converges a list of branching functions into a single function and returns the result.
|
||||
cover: cherry-trees
|
||||
dateModified: 2021-01-08T00:23:44+02:00
|
||||
---
|
||||
|
||||
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 `converger` with the results of all other functions.
|
||||
|
||||
```js
|
||||
const converge = (converger, fns) => (...args) =>
|
||||
converger(...fns.map(fn => fn.apply(null, args)));
|
||||
```
|
||||
|
||||
```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
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Copy sign to number
|
||||
type: snippet
|
||||
tags: [math]
|
||||
cover: keyboard-tea
|
||||
dateModified: 2020-10-07T23:52:57+03:00
|
||||
---
|
||||
|
||||
Returns the absolute value of the first number, but the sign of the second.
|
||||
|
||||
- Use `Math.sign()` to check if the two numbers have the same sign.
|
||||
- Return `x` if they do, `-x` otherwise.
|
||||
|
||||
```js
|
||||
const copySign = (x, y) => Math.sign(x) === Math.sign(y) ? x : -x;
|
||||
```
|
||||
|
||||
```js
|
||||
copySign(2, 3); // 2
|
||||
copySign(2, -3); // -2
|
||||
copySign(-2, 3); // 2
|
||||
copySign(-2, -3); // -2
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Copy to clipboard async
|
||||
type: snippet
|
||||
tags: [browser,string,promise]
|
||||
cover: typing
|
||||
dateModified: 2022-01-11T05:00:00-04:00
|
||||
---
|
||||
|
||||
Copies a string to the clipboard, returning a promise that resolves when the clipboard's contents have been updated.
|
||||
|
||||
- Check if the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) is available. Use an `if` statement to ensure `Navigator`, `Navigator.clipboard` and `Navigator.clipboard.writeText` are truthy.
|
||||
- Use `Clipboard.writeText()` to write the given value, `str`, to the clipboard.
|
||||
- Return the result of `Clipboard.writeText()`, which is a promise that resolves when the clipboard's contents have been updated.
|
||||
- In case that the Clipboard API is not available, use `Promise.reject()` to reject with an appropriate message.
|
||||
- **Note:** If you need to support older browsers, you might want to use `Document.execCommand()` instead. You can find out more about it in the [copyToClipboard snippet](/js/s/copy-to-clipboard).
|
||||
|
||||
```js
|
||||
const copyToClipboardAsync = str => {
|
||||
if (navigator && navigator.clipboard && navigator.clipboard.writeText)
|
||||
return navigator.clipboard.writeText(str);
|
||||
return Promise.reject('The Clipboard API is not available.');
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
copyToClipboardAsync('Lorem ipsum'); // 'Lorem ipsum' copied to clipboard.
|
||||
```
|
||||
@ -1,43 +0,0 @@
|
||||
---
|
||||
title: Copy to clipboard
|
||||
type: snippet
|
||||
tags: [browser,string,event]
|
||||
cover: typing
|
||||
dateModified: 2022-01-11T09:32:04+02:00
|
||||
---
|
||||
|
||||
Copies a string to the clipboard.
|
||||
Only works as a result of user action (i.e. inside a `click` event listener).
|
||||
|
||||
- Create a new `<textarea>` element, fill it with the supplied data and add it to the HTML document.
|
||||
- Use `Selection.getRangeAt()`to store the selected range (if any).
|
||||
- Use `Document.execCommand()` to copy to the clipboard.
|
||||
- Remove the `<textarea>` element from the HTML document.
|
||||
- Finally, use `Selection.addRange()` to recover the original selected range (if any).
|
||||
- **Note:** You can use the asynchronous [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) in most current browsers. You can find out more about it in the [copyToClipboardAsync snippet](/js/s/copy-to-clipboard-async).
|
||||
|
||||
```js
|
||||
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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
copyToClipboard('Lorem ipsum'); // 'Lorem ipsum' copied to clipboard.
|
||||
```
|
||||
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Count grouped elements
|
||||
type: snippet
|
||||
tags: [array,object]
|
||||
cover: tools
|
||||
dateModified: 2020-11-03T22:11:18+02:00
|
||||
---
|
||||
|
||||
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;
|
||||
}, {});
|
||||
```
|
||||
|
||||
```js
|
||||
countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2}
|
||||
countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1}
|
||||
countBy([{ count: 5 }, { count: 10 }, { count: 5 }], x => x.count)
|
||||
// {5: 2, 10: 1}
|
||||
```
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Count occurrences
|
||||
type: snippet
|
||||
tags: [array]
|
||||
cover: dark-leaves-4
|
||||
dateModified: 2020-10-18T23:04:45+03:00
|
||||
---
|
||||
|
||||
Counts the occurrences of a value in an array.
|
||||
|
||||
- Use `Array.prototype.reduce()` to increment a counter each time the specific value is encountered inside the array.
|
||||
|
||||
```js
|
||||
const countOccurrences = (arr, val) =>
|
||||
arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
|
||||
```
|
||||
|
||||
```js
|
||||
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3
|
||||
```
|
||||
@ -1,31 +0,0 @@
|
||||
---
|
||||
title: Count substrings of string
|
||||
type: snippet
|
||||
tags: [string,algorithm]
|
||||
author: chalarangelo
|
||||
cover: obelisk
|
||||
dateModified: 2021-01-08T00:23:44+02:00
|
||||
---
|
||||
|
||||
Counts the occurrences of a substring in a given string.
|
||||
|
||||
- Use `Array.prototype.indexOf()` to look for `searchValue` in `str`.
|
||||
- Increment a counter if the value is found and update the index, `i`.
|
||||
- Use a `while` loop that will return as soon as the value returned from `Array.prototype.indexOf()` is `-1`.
|
||||
|
||||
```js
|
||||
const countSubstrings = (str, searchValue) => {
|
||||
let count = 0,
|
||||
i = 0;
|
||||
while (true) {
|
||||
const r = str.indexOf(searchValue, i);
|
||||
if (r !== -1) [count, i] = [count + 1, r + 1];
|
||||
else return count;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
countSubstrings('tiktok tok tok tik tok tik', 'tik'); // 3
|
||||
countSubstrings('tutut tut tut', 'tut'); // 4
|
||||
```
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
title: Count weekdays between two dates
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: organizer
|
||||
dateModified: 2020-10-20T11:21:07+03:00
|
||||
---
|
||||
|
||||
Counts the weekdays between two dates.
|
||||
|
||||
- Use `Array.from()` to construct an array with `length` equal to the number of days between `startDate` and `endDate`.
|
||||
- Use `Array.prototype.reduce()` to iterate over the array, checking if each date is a weekday and incrementing `count`.
|
||||
- Update `startDate` with the next day each loop using `Date.prototype.getDate()` and `Date.prototype.setDate()` to advance it by one day.
|
||||
- **NOTE:** Does not take official holidays into account.
|
||||
|
||||
```js
|
||||
const countWeekDaysBetween = (startDate, endDate) =>
|
||||
Array
|
||||
.from({ length: (endDate - startDate) / (1000 * 3600 * 24) })
|
||||
.reduce(count => {
|
||||
if (startDate.getDay() % 6 !== 0) count++;
|
||||
startDate = new Date(startDate.setDate(startDate.getDate() + 1));
|
||||
return count;
|
||||
}, 0);
|
||||
```
|
||||
|
||||
```js
|
||||
countWeekDaysBetween(new Date('Oct 05, 2020'), new Date('Oct 06, 2020')); // 1
|
||||
countWeekDaysBetween(new Date('Oct 05, 2020'), new Date('Oct 14, 2020')); // 7
|
||||
```
|
||||
@ -1,34 +0,0 @@
|
||||
---
|
||||
title: Counter
|
||||
type: snippet
|
||||
tags: [browser]
|
||||
cover: touch-flower
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Creates a counter with the specified range, step and duration for the specified selector.
|
||||
|
||||
- Check if `step` has the proper sign and change it accordingly.
|
||||
- Use `setInterval()` in combination with `Math.abs()` and `Math.floor()` to calculate the time between each new text draw.
|
||||
- Use `Document.querySelector()`, `Element.innerHTML` to update the value of the selected element.
|
||||
- Omit the fourth argument, `step`, to use a default step of `1`.
|
||||
- Omit the fifth argument, `duration`, to use a default duration of `2000`ms.
|
||||
|
||||
```js
|
||||
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;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
counter('#my-id', 1, 1000, 5, 2000);
|
||||
// Creates a 2-second timer for the element with id="my-id"
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Create directory if not exists
|
||||
type: snippet
|
||||
tags: [node]
|
||||
cover: sunrise-over-city
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
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;
|
||||
```
|
||||
|
||||
```js
|
||||
createDirIfNotExists('test');
|
||||
// creates the directory 'test', if it doesn't exist
|
||||
```
|
||||
@ -1,32 +0,0 @@
|
||||
---
|
||||
title: Create HTML element
|
||||
type: snippet
|
||||
tags: [browser]
|
||||
cover: flower-portrait-4
|
||||
excerpt: Creates an element from a string without appending it to the document.
|
||||
dateModified: 2020-10-19T18:51:03+03:00
|
||||
---
|
||||
|
||||
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.
|
||||
- Use `Element.innerHTML` to set its inner HTML to the string supplied as the argument.
|
||||
- Use `Element.firstElementChild` to return the element version of the string.
|
||||
|
||||
```js
|
||||
const createElement = str => {
|
||||
const el = document.createElement('div');
|
||||
el.innerHTML = str;
|
||||
return el.firstElementChild;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
const el = createElement(
|
||||
`<div class="container">
|
||||
<p>Hello!</p>
|
||||
</div>`
|
||||
);
|
||||
console.log(el.className); // 'container'
|
||||
```
|
||||
@ -1,53 +0,0 @@
|
||||
---
|
||||
title: Create event hub
|
||||
type: snippet
|
||||
tags: [browser,event]
|
||||
cover: city-view
|
||||
excerpt: Creates a pub/sub event hub with emit, on, and off methods.
|
||||
dateModified: 2020-09-15T16:28:04+03:00
|
||||
---
|
||||
|
||||
Creates a pub/sub ([publish–subscribe](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern)) event hub with `emit`, `on`, and `off` methods.
|
||||
|
||||
- Use `Object.create()` with an argument of `null` to create an empty `hub` object that does not inherit properties from `Object.prototype`.
|
||||
- For `emit`, resolve the array of handlers based on the `event` argument and then run each one with `Array.prototype.forEach()` by passing in the data as an argument.
|
||||
- For `on`, create an array for the event if it does not yet exist, then use `Array.prototype.push()` to add the handler
|
||||
- to the array.
|
||||
- For `off`, use `Array.prototype.findIndex()` to find the index of the handler in the event array and remove it using `Array.prototype.splice()`.
|
||||
|
||||
```js
|
||||
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);
|
||||
if (this.hub[event].length === 0) delete this.hub[event];
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```js
|
||||
const handler = data => console.log(data);
|
||||
const hub = createEventHub();
|
||||
let increment = 0;
|
||||
|
||||
// Subscribe: listen for different types of events
|
||||
hub.on('message', handler);
|
||||
hub.on('message', () => console.log('Message event fired'));
|
||||
hub.on('increment', () => increment++);
|
||||
|
||||
// Publish: emit events to invoke all handlers subscribed to them, passing the data to them as an argument
|
||||
hub.emit('message', 'hello world'); // logs 'hello world' and 'Message event fired'
|
||||
hub.emit('message', { hello: 'world' }); // logs the object and 'Message event fired'
|
||||
hub.emit('increment'); // `increment` variable is now 1
|
||||
|
||||
// Unsubscribe: stop a specific handler from listening to the 'message' event
|
||||
hub.off('message', handler);
|
||||
```
|
||||
@ -1,30 +0,0 @@
|
||||
---
|
||||
title: CSV to array
|
||||
type: snippet
|
||||
tags: [string,array]
|
||||
cover: keyboard-tea
|
||||
dateModified: 2022-01-30T12:14:39+02:00
|
||||
---
|
||||
|
||||
Converts a comma-separated values (CSV) string to a 2D array.
|
||||
|
||||
- Use `Array.prototype.indexOf()` to find the first newline character (`\n`).
|
||||
- Use `Array.prototype.slice()` to remove the first row (title row) if `omitFirstRow` is `true`.
|
||||
- Use `String.prototype.split()` to create a string for each row.
|
||||
- Use `String.prototype.split()` to separate the values in each row, using the provided `delimiter`.
|
||||
- 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));
|
||||
```
|
||||
|
||||
```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']];
|
||||
```
|
||||
@ -1,40 +0,0 @@
|
||||
---
|
||||
title: CSV to JSON
|
||||
type: snippet
|
||||
tags: [string,object]
|
||||
cover: kettle-laptop
|
||||
dateModified: 2022-01-30T12:14:39+02:00
|
||||
---
|
||||
|
||||
Converts a comma-separated values (CSV) string to a 2D array of objects.
|
||||
The first row of the string is used as the title row.
|
||||
|
||||
- Use `Array.prototype.indexOf()` to find the first newline character (`\n`).
|
||||
- Use `Array.prototype.slice()` to remove the first row (title row) and `String.prototype.split()` to separate it into values, using the provided `delimiter`.
|
||||
- Use `String.prototype.split()` to create a string for each row.
|
||||
- Use `String.prototype.split()` to separate the values in each row, using the provided `delimiter`.
|
||||
- Use `Array.prototype.reduce()` to create an object for each row's values, with the keys parsed from the title row.
|
||||
- Omit the second argument, `delimiter`, to use a default delimiter of `,`.
|
||||
|
||||
```js
|
||||
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),
|
||||
{}
|
||||
);
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
CSVToJSON('col1,col2\na,b\nc,d');
|
||||
// [{'col1': 'a', 'col2': 'b'}, {'col1': 'c', 'col2': 'd'}];
|
||||
CSVToJSON('col1;col2\na;b\nc;d', ';');
|
||||
// [{'col1': 'a', 'col2': 'b'}, {'col1': 'c', 'col2': 'd'}];
|
||||
```
|
||||
@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Current URL
|
||||
type: snippet
|
||||
tags: [browser]
|
||||
cover: tropical-bike
|
||||
dateModified: 2020-10-20T11:46:23+03:00
|
||||
---
|
||||
|
||||
Returns the current URL.
|
||||
|
||||
- Use `Window.location.href` to get the current URL.
|
||||
|
||||
```js
|
||||
const currentURL = () => window.location.href;
|
||||
```
|
||||
|
||||
```js
|
||||
currentURL(); // 'https://www.google.com/'
|
||||
```
|
||||
@ -1,24 +0,0 @@
|
||||
---
|
||||
title: Curry function
|
||||
type: snippet
|
||||
tags: [function,recursion]
|
||||
cover: rocky-beach-2
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Curries a function.
|
||||
|
||||
- Use recursion.
|
||||
- If the number of provided arguments (`args`) is sufficient, call the passed function `fn`.
|
||||
- Otherwise, use `Function.prototype.bind()` to 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);
|
||||
```
|
||||
|
||||
```js
|
||||
curry(Math.pow)(2)(10); // 1024
|
||||
curry(Math.min, 3)(10)(50)(2); // 2
|
||||
```
|
||||
@ -1,31 +0,0 @@
|
||||
---
|
||||
title: Cycle generator
|
||||
type: snippet
|
||||
tags: [function,generator]
|
||||
author: chalarangelo
|
||||
cover: secret-tree
|
||||
dateModified: 2020-10-11T17:05:38+03:00
|
||||
---
|
||||
|
||||
Creates a generator, looping over the given array indefinitely.
|
||||
|
||||
- Use a non-terminating `while` loop, that will `yield` a value every time `Generator.prototype.next()` is called.
|
||||
- Use the module operator (`%`) with `Array.prototype.length` to get the next value's index and increment the counter after each `yield` statement.
|
||||
|
||||
```js
|
||||
const cycleGenerator = function* (arr) {
|
||||
let i = 0;
|
||||
while (true) {
|
||||
yield arr[i % arr.length];
|
||||
i++;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
const binaryCycle = cycleGenerator([0, 1]);
|
||||
binaryCycle.next(); // { value: 0, done: false }
|
||||
binaryCycle.next(); // { value: 1, done: false }
|
||||
binaryCycle.next(); // { value: 0, done: false }
|
||||
binaryCycle.next(); // { value: 1, done: false }
|
||||
```
|
||||
@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Date range generator
|
||||
type: snippet
|
||||
tags: [date,function,generator]
|
||||
cover: portal-timelapse
|
||||
dateModified: 2021-06-21T05:00:00-04:00
|
||||
---
|
||||
|
||||
Creates a generator, that generates all dates in the given range using the given step.
|
||||
|
||||
- Use a `while` loop to iterate from `start` to `end`, using `yield` to return each date in the range, using the `Date` constructor.
|
||||
- Use `Date.prototype.getDate()` and `Date.prototype.setDate()` to increment by `step` days after returning each subsequent value.
|
||||
- Omit the third argument, `step`, to use a default value of `1`.
|
||||
|
||||
```js
|
||||
const dateRangeGenerator = function* (start, end, step = 1) {
|
||||
let d = start;
|
||||
while (d < end) {
|
||||
yield new Date(d);
|
||||
d.setDate(d.getDate() + step);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
[...dateRangeGenerator(new Date('2021-06-01'), new Date('2021-06-04'))];
|
||||
// [ 2021-06-01, 2021-06-02, 2021-06-03 ]
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Day name
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: interior
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Gets the name of the weekday from a `Date` object.
|
||||
|
||||
- Use `Date.prototype.toLocaleDateString()` with the `{ weekday: 'long' }` option to retrieve the weekday.
|
||||
- Use the optional second argument to get a language-specific name or omit it to use the default locale.
|
||||
|
||||
```js
|
||||
const dayName = (date, locale) =>
|
||||
date.toLocaleDateString(locale, { weekday: 'long' });
|
||||
```
|
||||
|
||||
```js
|
||||
dayName(new Date()); // 'Saturday'
|
||||
dayName(new Date('09/23/2020'), 'de-DE'); // 'Samstag'
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Day of year
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: interior-3
|
||||
dateModified: 2020-10-19T18:51:03+03:00
|
||||
---
|
||||
|
||||
Gets the day of the year (number in the range 1-366) from a `Date` object.
|
||||
|
||||
- Use the `Date` constructor and `Date.prototype.getFullYear()` to get the first day of the year as a `Date` object.
|
||||
- Subtract the first day of the year from `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);
|
||||
```
|
||||
|
||||
```js
|
||||
dayOfYear(new Date()); // 272
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Days ago
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: sunrise-over-city
|
||||
dateModified: 2022-01-30T11:48:07+03:00
|
||||
---
|
||||
|
||||
Calculates the date of `n` days ago from today as a string representation.
|
||||
|
||||
- Use the `Date` constructor to get the current date.
|
||||
- Use `Math.abs()` and `Date.prototype.getDate()` to update the date accordingly and set to the result using `Date.prototype.setDate()`.
|
||||
- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.
|
||||
|
||||
```js
|
||||
const daysAgo = n => {
|
||||
let d = new Date();
|
||||
d.setDate(d.getDate() - Math.abs(n));
|
||||
return d.toISOString().split('T')[0];
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
daysAgo(20); // 2020-09-16 (if current date is 2020-10-06)
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: Days from now
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: tent-stars
|
||||
dateModified: 2022-01-30T11:48:07+03:00
|
||||
---
|
||||
|
||||
Calculates the date of `n` days from today as a string representation.
|
||||
|
||||
- Use the `Date` constructor to get the current date.
|
||||
- Use `Math.abs()` and `Date.prototype.getDate()` to update the date accordingly and set to the result using `Date.prototype.setDate()`.
|
||||
- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.
|
||||
|
||||
```js
|
||||
const daysFromNow = n => {
|
||||
let d = new Date();
|
||||
d.setDate(d.getDate() + Math.abs(n));
|
||||
return d.toISOString().split('T')[0];
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
daysFromNow(5); // 2020-10-13 (if current date is 2020-10-08)
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Number of days in month
|
||||
type: snippet
|
||||
tags: [date]
|
||||
cover: laptop-plants-2
|
||||
dateModified: 2021-06-13T05:00:00-04:00
|
||||
---
|
||||
|
||||
Gets the number of days in the given `month` of the specified `year`.
|
||||
|
||||
- Use the `Date` constructor to create a date from the given `year` and `month`.
|
||||
- Set the days parameter to `0` to get the last day of the previous month, as months are zero-indexed.
|
||||
- Use `Date.prototype.getDate()` to return the number of days in the given `month`.
|
||||
|
||||
```js
|
||||
const daysInMonth = (year, month) => new Date(year, month, 0).getDate();
|
||||
```
|
||||
|
||||
```js
|
||||
daysInMonth(2020, 12)); // 31
|
||||
daysInMonth(2024, 2)); // 29
|
||||
```
|
||||
@ -1,52 +0,0 @@
|
||||
---
|
||||
title: Debounce promise
|
||||
type: snippet
|
||||
tags: [function,promise]
|
||||
excerpt: Creates a debounced function that returns a promise.
|
||||
cover: ice
|
||||
dateModified: 2020-10-19T18:51:03+03:00
|
||||
---
|
||||
|
||||
Creates a debounced function that returns a promise, but delays invoking the provided function until at least `ms` milliseconds have elapsed since the last time it was invoked.
|
||||
All promises returned during this time will return the same data.
|
||||
|
||||
- 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.
|
||||
- Create a new `Promise` and add its `resolve` and `reject` callbacks to the `pending` promises stack.
|
||||
- When `setTimeout()` is called, copy the current stack (as it can change between the provided function call and its resolution), clear it and call the provided function.
|
||||
- When the provided function resolves/rejects, resolve/reject all promises in the stack (copied when the function was called) with the returned data.
|
||||
- Omit the second argument, `ms`, to set the timeout at a default of `0` ms.
|
||||
|
||||
```js
|
||||
const debouncePromise = (fn, ms = 0) => {
|
||||
let timeoutId;
|
||||
const pending = [];
|
||||
return (...args) =>
|
||||
new Promise((res, rej) => {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
const currentPending = [...pending];
|
||||
pending.length = 0;
|
||||
Promise.resolve(fn.apply(this, args)).then(
|
||||
data => {
|
||||
currentPending.forEach(({ resolve }) => resolve(data));
|
||||
},
|
||||
error => {
|
||||
currentPending.forEach(({ reject }) => reject(error));
|
||||
}
|
||||
);
|
||||
}, ms);
|
||||
pending.push({ resolve: res, reject: rej });
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
const fn = arg => new Promise(resolve => {
|
||||
setTimeout(resolve, 1000, ['resolved', arg]);
|
||||
});
|
||||
const debounced = debouncePromise(fn, 200);
|
||||
debounced('foo').then(console.log);
|
||||
debounced('bar').then(console.log);
|
||||
// Will log ['resolved', 'bar'] both times
|
||||
```
|
||||
@ -1,34 +0,0 @@
|
||||
---
|
||||
title: Debounce function
|
||||
type: snippet
|
||||
tags: [function]
|
||||
cover: solitude-beach
|
||||
excerpt: Creates a debounced function that waits `ms` milliseconds before invoking the provided function again.
|
||||
dateModified: 2021-10-13T19:29:39+02:00
|
||||
---
|
||||
|
||||
Creates a debounced function that delays invoking the provided function until at least `ms` milliseconds have elapsed since its last invocation.
|
||||
|
||||
- Each time the debounced function is invoked, clear the current pending timeout with `clearTimeout()`. Use `setTimeout()` to create a new timeout that delays invoking the function until at least `ms` milliseconds have 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);
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
window.addEventListener(
|
||||
'resize',
|
||||
debounce(() => {
|
||||
console.log(window.innerWidth);
|
||||
console.log(window.innerHeight);
|
||||
}, 250)
|
||||
); // Will log the window dimensions at most every 250ms
|
||||
```
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Decapitalize string
|
||||
type: snippet
|
||||
tags: [string]
|
||||
cover: forest-balcony
|
||||
dateModified: 2020-11-01T20:50:57+02:00
|
||||
---
|
||||
|
||||
Decapitalizes the first letter of a string.
|
||||
|
||||
- Use array destructuring and `String.prototype.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` argument 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(''));
|
||||
```
|
||||
|
||||
```js
|
||||
decapitalize('FooBar'); // 'fooBar'
|
||||
decapitalize('FooBar', true); // 'fOOBAR'
|
||||
```
|
||||
@ -1,38 +0,0 @@
|
||||
---
|
||||
title: Deep clone object
|
||||
type: snippet
|
||||
tags: [object,recursion]
|
||||
cover: neon-desk-2
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
Creates a deep clone of an object.
|
||||
Clones primitives, arrays and objects, excluding class instances.
|
||||
|
||||
- Use recursion.
|
||||
- Check if the passed object is `null` and, if so, return `null`.
|
||||
- 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.
|
||||
- If the object is an `Array`, set the `clone`'s `length` to that of the original and use `Array.from()` to create a clone.
|
||||
|
||||
```js
|
||||
const deepClone = obj => {
|
||||
if (obj === null) return null;
|
||||
let clone = Object.assign({}, obj);
|
||||
Object.keys(clone).forEach(
|
||||
key =>
|
||||
(clone[key] =
|
||||
typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
|
||||
);
|
||||
if (Array.isArray(obj)) {
|
||||
clone.length = obj.length;
|
||||
return Array.from(clone);
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
```
|
||||
|
||||
```js
|
||||
const a = { foo: 'bar', obj: { a: 1, b: 2 } };
|
||||
const b = deepClone(a); // a !== b, a.obj !== b.obj
|
||||
```
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Deep flatten array
|
||||
type: snippet
|
||||
tags: [array,recursion]
|
||||
cover: digital-nomad-4
|
||||
dateModified: 2020-10-22T20:23:47+03:00
|
||||
---
|
||||
|
||||
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)));
|
||||
```
|
||||
|
||||
```js
|
||||
deepFlatten([1, [2], [[3], 4], 5]); // [1, 2, 3, 4, 5]
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user