[
  {
    "code": "const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>\n  data\n    .slice(omitFirstRow ? data.indexOf('\\n') + 1 : 0)\n    .split('\\n')\n    .map(v => v.split(delimiter));",
    "description": "Converts a comma-separated values (CSV) string to a 2D array.\n\n- Use `Array.prototype.slice()` and `Array.prototype.indexOf('\\n')` to remove the first row (title row) if `omitFirstRow` is `true`.\n- Use `String.prototype.split('\\n')` to create a string for each row, then `String.prototype.split(delimiter)` to separate the values in each row.\n- Omit the second argument, `delimiter`, to use a default delimiter of `','`.\n- Omit the third argument, `omitFirstRow`, to include the first row (title row) of the CSV string.",
    "example": "CSVToArray('a,b\\nc,d'); // [['a', 'b'], ['c', 'd']];\nCSVToArray('a;b\\nc;d', ';'); // [['a', 'b'], ['c', 'd']];\nCSVToArray('col1,col2\\na,b\\nc,d', ',', true); // [['a', 'b'], ['c', 'd']];",
    "id": "CSVToArray",
    "tags": [
      "string",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const CSVToJSON = (data, delimiter = ',') => {\n  const titles = data.slice(0, data.indexOf('\\n')).split(delimiter);\n  return data\n    .slice(data.indexOf('\\n') + 1)\n    .split('\\n')\n    .map(v => {\n      const values = v.split(delimiter);\n      return titles.reduce(\n        (obj, title, index) => ((obj[title] = values[index]), obj),\n        {}\n      );\n    });\n};",
    "description": "Converts a comma-separated values (CSV) string to a 2D array of objects.\nThe first row of the string is used as the title row.\n\n- Use `Array.prototype.slice()` and `Array.prototype.indexOf('\\n')` and `String.prototype.split(delimiter)` to separate the first row (title row) into values.\n- Use `String.prototype.split('\\n')` to create a string for each row, then `Array.prototype.map()` and `String.prototype.split(delimiter)` to separate the values in each row.\n- Use `Array.prototype.reduce()` to create an object for each row's values, with the keys parsed from the title row.\n- Omit the second argument, `delimiter`, to use a default delimiter of `,`.",
    "example": "CSVToJSON('col1,col2\\na,b\\nc,d');\n// [{'col1': 'a', 'col2': 'b'}, {'col1': 'c', 'col2': 'd'}];\nCSVToJSON('col1;col2\\na;b\\nc;d', ';');\n// [{'col1': 'a', 'col2': 'b'}, {'col1': 'c', 'col2': 'd'}];",
    "id": "CSVToJSON",
    "tags": [
      "string",
      "object",
      "advanced"
    ]
  },
  {
    "code": "const HSBToRGB = (h, s, b) => {\n  s /= 100;\n  b /= 100;\n  const k = (n) => (n + h / 60) % 6;\n  const f = (n) => b * (1 - s * Math.max(0, Math.min(k(n), 4 - k(n), 1)));\n  return [255 * f(5), 255 * f(3), 255 * f(1)];\n};",
    "description": "Converts a HSB color tuple to RGB format.\n\n- Use the [HSB to RGB conversion formula](https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB) to convert to the appropriate format.\n- The range of the input parameters is H: [0, 360], S: [0, 100], B: [0, 100].\n- The range of all output values is [0, 255].",
    "example": "HSBToRGB(18, 81, 99); // [252.45, 109.31084999999996, 47.965499999999984]",
    "id": "HSBToRGB",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const HSLToRGB = (h, s, l) => {\n  s /= 100;\n  l /= 100;\n  const k = n => (n + h / 30) % 12;\n  const a = s * Math.min(l, 1 - l);\n  const f = n =>\n    l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));\n  return [255 * f(0), 255 * f(8), 255 * f(4)];\n};",
    "description": "Converts a HSL color tuple to RGB format.\n\n- Use the [HSL to RGB conversion formula](https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB) to convert to the appropriate format.\n- The range of the input parameters is H: [0, 360], S: [0, 100], L: [0, 100].\n- The range of all output values is [0, 255].",
    "example": "HSLToRGB(13, 100, 11); // [56.1, 12.155, 0]",
    "id": "HSLToRGB",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const fs = require('fs');\n\nconst JSONToFile = (obj, filename) =>\n  fs.writeFileSync(\\`\\${filename}.json\\`, JSON.stringify(obj, null, 2));",
    "description": "Writes a JSON object to a file.\n\n- Use `fs.writeFileSync()`, template literals and `JSON.stringify()` to write a `json` object to a `.json` file.",
    "example": "JSONToFile({ test: 'is passed' }, 'testJsonFile');\n// writes the object to 'testJsonFile.json'",
    "id": "JSONToFile",
    "tags": [
      "node",
      "intermediate"
    ]
  },
  {
    "code": "const JSONtoCSV = (arr, columns, delimiter = ',') =>\n  [\n    columns.join(delimiter),\n    ...arr.map(obj =>\n      columns.reduce(\n        (acc, key) =>\n          \\`\\${acc}\\${!acc.length ? '' : delimiter}\"\\${!obj[key] ? '' : obj[key]}\"\\`,\n        ''\n      )\n    ),\n  ].join('\\n');",
    "description": "Converts an array of objects to a comma-separated values (CSV) string that contains only the `columns` specified.\n\n- Use `Array.prototype.join(delimiter)` to combine all the names in `columns` to create the first row.\n- Use `Array.prototype.map()` and `Array.prototype.reduce()` to create a row for each object. Substitute non-existent values with empty strings and only mapping values in `columns`.\n- Use `Array.prototype.join('\\n')` to combine all rows into a string.\n- Omit the third argument, `delimiter`, to use a default delimiter of `','`.",
    "example": "JSONtoCSV(\n  [{ a: 1, b: 2 }, { a: 3, b: 4, c: 5 }, { a: 6 }, { b: 7 }],\n  ['a', 'b']\n); // 'a,b\\n\"1\",\"2\"\\n\"3\",\"4\"\\n\"6\",\"\"\\n\"\",\"7\"'\nJSONtoCSV(\n  [{ a: 1, b: 2 }, { a: 3, b: 4, c: 5 }, { a: 6 }, { b: 7 }],\n  ['a', 'b'],\n  ';'\n); // 'a;b\\n\"1\";\"2\"\\n\"3\";\"4\"\\n\"6\";\"\"\\n\"\";\"7\"'",
    "id": "JSONtoCSV",
    "tags": [
      "array",
      "string",
      "object",
      "advanced"
    ]
  },
  {
    "code": "const RGBToHSB = (r, g, b) => {\n  r /= 255;\n  g /= 255;\n  b /= 255;\n  const v = Math.max(r, g, b),\n    n = v - Math.min(r, g, b);\n  const h =\n    n === 0 ? 0 : n && v === r ? (g - b) / n : v === g ? 2 + (b - r) / n : 4 + (r - g) / n;\n  return [60 * (h < 0 ? h + 6 : h), v && (n / v) * 100, v * 100];\n};",
    "description": "Converts a RGB color tuple to HSB format.\n\n- Use the [RGB to HSB conversion formula](https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB) to convert to the appropriate format.\n- The range of all input parameters is [0, 255].\n- The range of the resulting values is H: [0, 360], S: [0, 100], B: [0, 100].",
    "example": "RGBToHSB(252, 111, 48);\n// [18.529411764705856, 80.95238095238095, 98.82352941176471]",
    "id": "RGBToHSB",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const RGBToHSL = (r, g, b) => {\n  r /= 255;\n  g /= 255;\n  b /= 255;\n  const l = Math.max(r, g, b);\n  const s = l - Math.min(r, g, b);\n  const h = s\n    ? l === r\n      ? (g - b) / s\n      : l === g\n      ? 2 + (b - r) / s\n      : 4 + (r - g) / s\n    : 0;\n  return [\n    60 * h < 0 ? 60 * h + 360 : 60 * h,\n    100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0),\n    (100 * (2 * l - s)) / 2,\n  ];\n};",
    "description": "Converts a RGB color tuple to HSL format.\n\n- Use the [RGB to HSL conversion formula](https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/) to convert to the appropriate format.\n- The range of all input parameters is [0, 255].\n- The range of the resulting values is H: [0, 360], S: [0, 100], L: [0, 100].",
    "example": "RGBToHSL(45, 23, 11); // [21.17647, 60.71428, 10.98039]",
    "id": "RGBToHSL",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const RGBToHex = (r, g, b) =>\n  ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');",
    "description": "Converts the values of RGB components to a hexadecimal color code.\n\n- Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (`<<`) and `Number.prototype.toString(16)`.\n- Use `String.prototype.padStart(6, '0')` to get a 6-digit hexadecimal value.",
    "example": "RGBToHex(255, 165, 1); // 'ffa501'",
    "id": "RGBToHex",
    "tags": [
      "string",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const URLJoin = (...args) =>\n  args\n    .join('/')\n    .replace(/[\\/]+/g, '/')\n    .replace(/^(.+):\\//, '$1://')\n    .replace(/^file:/, 'file:/')\n    .replace(/\\/(\\?|&|#[^!])/g, '$1')\n    .replace(/\\?/g, '&')\n    .replace('&', '?');",
    "description": "Joins all given URL segments together, then normalizes the resulting URL.\n\n- Use `String.prototype.join('/')` to combine URL segments.\n- Use a series of `String.prototype.replace()` calls with various regexps to normalize the resulting URL (remove double slashes, add proper slashes for protocol, remove slashes before parameters, combine parameters with `'&'` and normalize first parameter delimiter).",
    "example": "URLJoin('http://www.google.com', 'a', '/b/cd', '?foo=123', '?bar=foo');\n// 'http://www.google.com/a/b/cd?foo=123&bar=foo'",
    "id": "URLJoin",
    "tags": [
      "string",
      "regexp",
      "advanced"
    ]
  },
  {
    "code": "const UUIDGeneratorBrowser = () =>\n  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>\n    (\n      c ^\n      (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))\n    ).toString(16)\n  );",
    "description": "Generates a UUID in a browser.\n\n- Use `Crypto.getRandomValues()` to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4.\n- Use `Number.prototype.toString(16)` to convert it to a proper UUID.",
    "example": "UUIDGeneratorBrowser(); // '7982fcfe-5721-4632-bede-6000885be57d'",
    "id": "UUIDGeneratorBrowser",
    "tags": [
      "browser",
      "random",
      "intermediate"
    ]
  },
  {
    "code": "const crypto = require('crypto');\n\nconst UUIDGeneratorNode = () =>\n  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>\n    (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)\n  );",
    "description": "Generates a UUID in Node.JS.\n\n- Use `crypto.randomBytes()` to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4.\n- Use `Number.prototype.toString(16)` to convert it to a proper UUID.",
    "example": "UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc'",
    "id": "UUIDGeneratorNode",
    "tags": [
      "node",
      "random",
      "intermediate"
    ]
  },
  {
    "code": "const accumulate = (...nums) =>\n  nums.reduce((acc, n) => [...acc, n + +acc.slice(-1)], []);",
    "description": "Creates an array of partial sums.\n\n- Use `Array.prototype.reduce()`, initialized with an empty array accumulator to iterate over `nums`.\n- Use `Array.prototype.slice(-1)`, the spread operator (`...`) and the unary `+` operator to add each value to the accumulator array containing the previous sums.",
    "example": "accumulate(1, 2, 3, 4); // [1, 3, 6, 10]\naccumulate(...[1, 2, 3, 4]); // [1, 3, 6, 10]",
    "id": "accumulate",
    "tags": [
      "math",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const addClass = (el, className) => el.classList.add(className);",
    "description": "Adds a class to an HTML element.\n\n- Use `Element.classList` and `DOMTokenList.add()` to add the specified class to the element.",
    "example": "addClass(document.querySelector('p'), 'special');\n// The paragraph will now have the 'special' class",
    "id": "addClass",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const addDaysToDate = (date, n) => {\n  const d = new Date(date);\n  d.setDate(d.getDate() + n);\n  return d.toISOString().split('T')[0];\n};",
    "description": "Calculates the date of `n` days from the given date, returning its string representation.\n\n- Use `new Date()` to create a date object from the first argument.\n- Use `Date.prototype.getDate()` and `Date.prototype.setDate()` to add `n` days to the given date.\n- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.",
    "example": "addDaysToDate('2020-10-15', 10); // '2020-10-25'\naddDaysToDate('2020-10-15', -10); // '2020-10-05'",
    "id": "addDaysToDate",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const addEventListenerAll = (targets, type, listener, options, useCapture) => {\n  targets.forEach(target =>\n    target.addEventListener(type, listener, options, useCapture)\n  );\n};",
    "description": "Attaches an event listener to all the provided targets.\n\n- Use `Array.prototype.forEach()` and `EventTarget.addEventListener()` to attach the provided `listener` for the given event `type` to all `targets`.",
    "example": "addEventListenerAll(document.querySelectorAll('a'), 'click', () =>\n  console.log('Clicked a link')\n);\n// Logs 'Clicked a link' whenever any anchor element is clicked",
    "id": "addEventListenerAll",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const addMinutesToDate = (date, n) => {\n  const d = new Date(date);\n  d.setTime(d.getTime() + n * 60000);\n  return d.toISOString().split('.')[0].replace('T',' ');\n};",
    "description": "Calculates the date of `n` minutes from the given date, returning its string representation.\n\n- Use `new Date()` to create a date object from the first argument.\n- Use `Date.prototype.getTime()` and `Date.prototype.setTime()` to add `n` minutes to the given date.\n- Use `Date.prototype.toISOString()`, `String.prototype.split()` and `String.prototype.replace()` to return a string in `yyyy-mm-dd HH:MM:SS` format.",
    "example": "addMinutesToDate('2020-10-19 12:00:00', 10); // '2020-10-19 12:10:00'\naddMinutesToDate('2020-10-19', -10); // '2020-10-18 23:50:00'",
    "id": "addMinutesToDate",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const addMultipleListeners = (el, types, listener, options, useCapture) => {\n  types.forEach(type =>\n    el.addEventListener(type, listener, options, useCapture)\n  );\n};",
    "description": "Adds multiple event listeners with the same handler to an element.\n\n- Use `Array.prototype.forEach()` and `EventTarget.addEventListener()` to add multiple event listeners with an assigned callback function to an element.",
    "example": "addMultipleListeners(\n  document.querySelector('.my-element'),\n  ['click', 'mousedown'],\n  () => { console.log('hello!') }\n);",
    "id": "addMultipleListeners",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const addStyles = (el, styles) => Object.assign(el.style, styles);",
    "description": "Adds the provided styles to the given element.\n\n- Use `Object.assign()` and `ElementCSSInlineStyle.style` to merge the provided `styles` object into the style of the given element.",
    "example": "addStyles(document.getElementById('my-element'), {\n  background: 'red',\n  color: '#ffff00',\n  fontSize: '3rem'\n});",
    "id": "addStyles",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const addWeekDays = (startDate, count) =>\n  Array.from({ length: count }).reduce(date => {\n    date = new Date(date.setDate(date.getDate() + 1));\n    if (date.getDay() % 6 === 0)\n      date = new Date(date.setDate(date.getDate() + (date.getDay() / 6 + 1)));\n    return date;\n  }, startDate);",
    "description": "Calculates the date after adding the given number of business days.\n\n- Use `Array.from()` to construct an array with `length` equal to the `count` of business days to be added.\n- Use `Array.prototype.reduce()` to iterate over the array, starting from `startDate` and incrementing, using `Date.prototype.getDate()` and `Date.prototype.setDate()`.\n- If the current `date` is on a weekend, update it again by adding either one day or two days to make it a weekday.\n- **NOTE:** Does not take official holidays into account.",
    "example": "addWeekDays(new Date('Oct 09, 2020'), 5); // 'Oct 16, 2020'\naddWeekDays(new Date('Oct 12, 2020'), 5); // 'Oct 19, 2020'",
    "id": "addWeekDays",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const all = (arr, fn = Boolean) => arr.every(fn);",
    "description": "Checks if the provided predicate function returns `true` for all elements in a collection.\n\n- Use `Array.prototype.every()` to test if all elements in the collection return `true` based on `fn`.\n- Omit the second argument, `fn`, to use `Boolean` as a default.",
    "example": "all([4, 2, 3], x => x > 1); // true\nall([1, 2, 3]); // true",
    "id": "all",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const allEqual = arr => arr.every(val => val === arr[0]);",
    "description": "Checks if all elements in an array are equal.\n\n- Use `Array.prototype.every()` to check if all the elements of the array are the same as the first one.\n- Elements in the array are compared using the strict comparison operator, which does not account for `NaN` self-inequality.",
    "example": "allEqual([1, 2, 3, 4, 5, 6]); // false\nallEqual([1, 1, 1, 1]); // true",
    "id": "allEqual",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const allEqualBy = (arr, fn) => {\n  const eql = fn(arr[0]);\n  return arr.every(val => fn(val) === eql);\n};",
    "description": "Checks if all elements in an array are equal, based on the provided mapping function.\n\n- Apply `fn` to the first element of `arr`.\n- 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.\n- Elements in the array are compared using the strict comparison operator, which does not account for `NaN` self-inequality.",
    "example": "allEqualBy([1.1, 1.2, 1.3], Math.round); // true\nallEqualBy([1.1, 1.3, 1.6], Math.round); // false",
    "id": "allEqualBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const allUnique = arr => arr.length === new Set(arr).size;",
    "description": "Checks if all elements in an array are unique.\n\n- Create a new `Set` from the mapped values to keep only unique occurrences.\n- Use `Array.prototype.length` and `Set.prototype.size` to compare the length of the unique values to the original array.",
    "example": "allUnique([1, 2, 3, 4]); // true\nallUnique([1, 1, 2, 3]); // false",
    "id": "allUnique",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const allUniqueBy = (arr, fn) => arr.length === new Set(arr.map(fn)).size;",
    "description": "Checks if all elements in an array are unique, based on the provided mapping function.\n\n- Use `Array.prototype.map()` to apply `fn` to all elements in `arr`.\n- Create a new `Set` from the mapped values to keep only unique occurrences.\n- Use `Array.prototype.length` and `Set.prototype.size` to compare the length of the unique mapped values to the original array.",
    "example": "allUniqueBy([1.2, 2.4, 2.9], Math.round); // true\nallUniqueBy([1.2, 2.3, 2.4], Math.round); // false",
    "id": "allUniqueBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const and = (a, b) => a && b;",
    "description": "Checks if both arguments are `true`.\n\n- Use the logical and (`&&`) operator on the two given values.",
    "example": "and(true, true); // true\nand(true, false); // false\nand(false, false); // false",
    "id": "and",
    "tags": [
      "math",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const any = (arr, fn = Boolean) => arr.some(fn);",
    "description": "Checks if the provided predicate function returns `true` for at least one element in a collection.\n\n- Use `Array.prototype.some()` to test if any elements in the collection return `true` based on `fn`.\n- Omit the second argument, `fn`, to use `Boolean` as a default.",
    "example": "any([0, 1, 2, 0], x => x >= 2); // true\nany([0, 0, 1, 0]); // true",
    "id": "any",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const aperture = (n, arr) =>\n  n > arr.length\n    ? []\n    : arr.slice(n - 1).map((v, i) => arr.slice(i, i + n));",
    "description": "Creates an array of `n`-tuples of consecutive elements.\n\n- Use `Array.prototype.slice()` and `Array.prototype.map()` to create an array of appropriate length.\n- Populate the array with `n`-tuples of consecutive elements from `arr`.\n- If `n` is greater than the length of `arr`, return an empty array.",
    "example": "aperture(2, [1, 2, 3, 4]); // [[1, 2], [2, 3], [3, 4]]\naperture(3, [1, 2, 3, 4]); // [[1, 2, 3], [2, 3, 4]]\naperture(5, [1, 2, 3, 4]); // []",
    "id": "aperture",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const approximatelyEqual = (v1, v2, epsilon = 0.001) =>\n  Math.abs(v1 - v2) < epsilon;",
    "description": "Checks if two numbers are approximately equal to each other.\n\n- Use `Math.abs()` to compare the absolute difference of the two values to `epsilon`.\n- Omit the third argument, `epsilon`, to use a default value of `0.001`.",
    "example": "approximatelyEqual(Math.PI / 2.0, 1.5708); // true",
    "id": "approximatelyEqual",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const arithmeticProgression  = (n, lim) =>\n  Array.from({ length: Math.ceil(lim / n) }, (_, i) => (i + 1) * n );",
    "description": "Creates an array of numbers in the arithmetic progression, starting with the given positive integer and up to the specified limit.\n\n- 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.",
    "example": "arithmeticProgression(5, 25); // [5, 10, 15, 20, 25]",
    "id": "arithmeticProgression",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const arrayToCSV = (arr, delimiter = ',') =>\n  arr\n    .map(v =>\n      v.map(x => (isNaN(x) ? \\`\"\\${x.replace(/\"/g, '\"\"')}\"\\` : x)).join(delimiter)\n    )\n    .join('\\n');",
    "description": "Converts a 2D array to a comma-separated values (CSV) string.\n\n- Use `Array.prototype.map()` and `Array.prototype.join(delimiter)` to combine individual 1D arrays (rows) into strings.\n- Use `Array.prototype.join('\\n')` 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 `,`.",
    "example": "arrayToCSV([['a', 'b'], ['c', 'd']]); // '\"a\",\"b\"\\n\"c\",\"d\"'\narrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '\"a\";\"b\"\\n\"c\";\"d\"'\narrayToCSV([['a', '\"b\" great'], ['c', 3.1415]]);\n// '\"a\",\"\"\"b\"\" great\"\\n\"c\",3.1415'",
    "id": "arrayToCSV",
    "tags": [
      "array",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const arrayToHTMLList = (arr, listID) => \n  document.querySelector(\\`#\\${listID}\\`).innerHTML += arr\n    .map(item => \\`<li>\\${item}</li>\\`)\n    .join('');",
    "description": "Converts the given array elements into `<li>` tags and appends them to the list of the given id.\n\n- Use `Array.prototype.map()` and `Document.querySelector()` to create a list of html tags.",
    "example": "arrayToHTMLList(['item 1', 'item 2'], 'myListID');",
    "id": "arrayToHTMLList",
    "tags": [
      "browser",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const ary = (fn, n) => (...args) => fn(...args.slice(0, n));",
    "description": "Creates a function that accepts up to `n` arguments, ignoring any additional arguments.\n\n- Call the provided function, `fn`, with up to `n` arguments, using `Array.prototype.slice(0, n)` and the spread operator (`...`).",
    "example": "const firstTwoMax = ary(Math.max, 2);\n[[2, 6, 'a'], [6, 4, 8], [10]].map(x => firstTwoMax(...x)); // [6, 6, 10]",
    "id": "ary",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const assertValidKeys = (obj, keys) =>\n  Object.keys(obj).every(key => keys.includes(key));",
    "description": "Validates all keys in an object match the given `keys`.\n\n- Use `Object.keys()` to get the keys of the given object, `obj`.\n- Use `Array.prototype.every()` and `Array.prototype.includes()` to validate that each key in the object is specified in the `keys` array.",
    "example": "assertValidKeys({ id: 10, name: 'apple' }, ['id', 'name']); // true\nassertValidKeys({ id: 10, name: 'apple' }, ['id', 'type']); // false",
    "id": "assertValidKeys",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const atob = str => Buffer.from(str, 'base64').toString('binary');",
    "description": "Decodes a string of data which has been encoded using base-64 encoding.\n\n- Create a `Buffer` for the given string with base-64 encoding and use `Buffer.toString('binary')` to return the decoded string.",
    "example": "atob('Zm9vYmFy'); // 'foobar'",
    "id": "atob",
    "tags": [
      "node",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const attempt = (fn, ...args) => {\n  try {\n    return fn(...args);\n  } catch (e) {\n    return e instanceof Error ? e : new Error(e);\n  }\n};",
    "description": "Attempts to invoke a function with the provided arguments, returning either the result or the caught error object.\n\n- Use a `try... catch` block to return either the result of the function or an appropriate error.\n- If the caught object is not an `Error`, use it to create a new `Error`.",
    "example": "var elements = attempt(function(selector) {\n  return document.querySelectorAll(selector);\n}, '>_>');\nif (elements instanceof Error) elements = []; // elements = []",
    "id": "attempt",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const average = (...nums) =>\n  nums.reduce((acc, val) => acc + val, 0) / nums.length;",
    "description": "Calculates the average of two or more numbers.\n\n- Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`.\n- Divide the resulting array by its length.",
    "example": "average(...[1, 2, 3]); // 2\naverage(1, 2, 3); // 2",
    "id": "average",
    "tags": [
      "math",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const averageBy = (arr, fn) =>\n  arr\n    .map(typeof fn === 'function' ? fn : val => val[fn])\n    .reduce((acc, val) => acc + val, 0) / arr.length;",
    "description": "Calculates the average of an array, after mapping each element to a value using the provided function.\n\n- Use `Array.prototype.map()` to map each element to the value returned by `fn`.\n- Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`.\n- Divide the resulting array by its length.",
    "example": "averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5\naverageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5",
    "id": "averageBy",
    "tags": [
      "math",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const bifurcate = (arr, filter) =>\n  arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [\n    [],\n    [],\n  ]);",
    "description": "Splits values into two groups, based on the result of the given `filter` array. \n\n- Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on `filter`.\n- If `filter` has a truthy value for any element, add it to the first group, otherwise add it to the second group.",
    "example": "bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]);\n// [ ['beep', 'boop', 'bar'], ['foo'] ]",
    "id": "bifurcate",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const bifurcateBy = (arr, fn) =>\n  arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [\n    [],\n    [],\n  ]);",
    "description": "Splits values into two groups, based on the result of the given filtering function. \n\n- Use `Array.prototype.reduce()` and `Array.prototype.push()` to add elements to groups, based on the value returned by `fn` for each element.\n- If `fn` returns a truthy value for any element, add it to the first group, otherwise add it to the second group.",
    "example": "bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b');\n// [ ['beep', 'boop', 'bar'], ['foo'] ]",
    "id": "bifurcateBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const binary = fn => (a, b) => fn(a, b);",
    "description": "Creates a function that accepts up to two arguments, ignoring any additional arguments.\n\n- Call the provided function, `fn`, with the first two arguments given.",
    "example": "['2', '1', '0'].map(binary(Math.max)); // [2, 1, 2]",
    "id": "binary",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const binarySearch = (arr, item) => {\n  let l = 0,\n    r = arr.length - 1;\n  while (l <= r) {\n    const mid = Math.floor((l + r) / 2);\n    const guess = arr[mid];\n    if (guess === item) return mid;\n    if (guess > item) r = mid - 1;\n    else l = mid + 1;\n  }\n  return -1;\n};",
    "description": "Finds the index of a given element in a sorted array using the binary search algorithm.\n\n- Declare the left and right search boundaries, `l` and `r`, initialized to `0` and the `length` of the array respectively.\n- Use a `while` loop to repeatedly narrow down the search subarray, using `Math.floor()` to cut it in half.\n- Return the index of the element if found, otherwise return `-1`.\n- **Note:** Does not account for duplicate values in the array.",
    "example": "binarySearch([1, 2, 3, 4, 5], 1); // 0\nbinarySearch([1, 2, 3, 4, 5], 5); // 4\nbinarySearch([1, 2, 3, 4, 5], 6); // -1",
    "id": "binarySearch",
    "tags": [
      "algorithm",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const bind = (fn, context, ...boundArgs) => (...args) =>\n  fn.apply(context, [...boundArgs, ...args]);",
    "description": "Creates a function that invokes `fn` with a given context, optionally prepending any additional supplied parameters to the arguments.\n\n- Return a `function` that uses `Function.prototype.apply()` to apply the given `context` to `fn`.\n- Use the spread operator (`...`) to prepend any additional supplied parameters to the arguments.",
    "example": "function greet(greeting, punctuation) {\n  return greeting + ' ' + this.user + punctuation;\n}\nconst freddy = { user: 'fred' };\nconst freddyBound = bind(greet, freddy);\nconsole.log(freddyBound('hi', '!')); // 'hi fred!'",
    "id": "bind",
    "tags": [
      "function",
      "object",
      "advanced"
    ]
  },
  {
    "code": "const bindAll = (obj, ...fns) =>\n  fns.forEach(\n    fn => (\n      (f = obj[fn]),\n      (obj[fn] = function() {\n        return f.apply(obj);\n      })\n    )\n  );",
    "description": "Binds methods of an object to the object itself, overwriting the existing method.\n\n- Use `Array.prototype.forEach()` to iterate over the given `fns`.\n- Return a function for each one, using `Function.prototype.apply()` to apply the given context (`obj`) to `fn`.",
    "example": "var view = {\n  label: 'docs',\n  click: function() {\n    console.log('clicked ' + this.label);\n  }\n};\nbindAll(view, 'click');\ndocument.body.addEventListener('click', view.click);\n// Log 'clicked docs' when clicked.",
    "id": "bindAll",
    "tags": [
      "object",
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const bindKey = (context, fn, ...boundArgs) => (...args) =>\n  context[fn].apply(context, [...boundArgs, ...args]);",
    "description": "Creates a function that invokes the method at a given key of an object, optionally prepending any additional supplied parameters to the arguments.\n\n- Return a `function` that uses `Function.prototype.apply()` to bind `context[fn]` to `context`.\n- Use the spread operator (`...`) to prepend any additional supplied parameters to the arguments.",
    "example": "const freddy = {\n  user: 'fred',\n  greet: function(greeting, punctuation) {\n    return greeting + ' ' + this.user + punctuation;\n  }\n};\nconst freddyBound = bindKey(freddy, 'greet');\nconsole.log(freddyBound('hi', '!')); // 'hi fred!'",
    "id": "bindKey",
    "tags": [
      "function",
      "object",
      "advanced"
    ]
  },
  {
    "code": "const binomialCoefficient = (n, k) => {\n  if (Number.isNaN(n) || Number.isNaN(k)) return NaN;\n  if (k < 0 || k > n) return 0;\n  if (k === 0 || k === n) return 1;\n  if (k === 1 || k === n - 1) return n;\n  if (n - k < k) k = n - k;\n  let res = n;\n  for (let j = 2; j <= k; j++) res *= (n - j + 1) / j;\n  return Math.round(res);\n};",
    "description": "Calculates the number of ways to choose `k` items from `n` items without repetition and without order.\n\n- Use `Number.isNaN()` to check if any of the two values is `NaN`.\n- Check if `k` is less than `0`, greater than or equal to `n`, equal to `1` or `n - 1` and return the appropriate result.\n- Check if `n - k` is less than `k` and switch their values accordingly.\n- Loop from `2` through `k` and calculate the binomial coefficient.\n- Use `Math.round()` to account for rounding errors in the calculation.",
    "example": "binomialCoefficient(8, 2); // 28",
    "id": "binomialCoefficient",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const both = (f, g) => (...args) => f(...args) && g(...args);",
    "description": "Checks if both of the given functions return `true` for a given set of arguments.\n\n- Use the logical and (`&&`) operator on the result of calling the two functions with the supplied `args`.",
    "example": "const isEven = num => num % 2 === 0;\nconst isPositive = num => num > 0;\nconst isPositiveEven = both(isEven, isPositive);\nisPositiveEven(4); // true\nisPositiveEven(-2); // false",
    "id": "both",
    "tags": [
      "function",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const bottomVisible = () =>\n  document.documentElement.clientHeight + window.scrollY >=\n  (document.documentElement.scrollHeight ||\n    document.documentElement.clientHeight);",
    "description": "Checks if the bottom of the page is visible.\n\n- Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible.",
    "example": "bottomVisible(); // true",
    "id": "bottomVisible",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const btoa = str => Buffer.from(str, 'binary').toString('base64');",
    "description": "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.\n\n- Create a `Buffer` for the given string with binary encoding and use `Buffer.toString('base64')` to return the encoded string.",
    "example": "btoa('foobar'); // 'Zm9vYmFy'",
    "id": "btoa",
    "tags": [
      "node",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const bubbleSort = arr => {\n  let swapped = false;\n  const a = [...arr];\n  for (let i = 1; i < a.length; i++) {\n    swapped = false;\n    for (let j = 0; j < a.length - i; j++) {\n      if (a[j + 1] < a[j]) {\n        [a[j], a[j + 1]] = [a[j + 1], a[j]];\n        swapped = true;\n      }\n    }\n    if (!swapped) return a;\n  }\n  return a;\n};",
    "description": "Sorts an array of numbers, using the bubble sort algorithm.\n\n- Declare a variable, `swapped`, that indicates if any values were swapped during the current iteration.\n- Use the spread operator (`...`) to clone the original array, `arr`.\n- Use a `for` loop to iterate over the elements of the cloned array, terminating before the last element.\n- 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`.\n- If `swapped` is `false` after an iteration, no more changes are needed, so the cloned array is returned.",
    "example": "bubbleSort([2, 1, 4, 3]); // [1, 2, 3, 4]",
    "id": "bubbleSort",
    "tags": [
      "algorithm",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const bucketSort = (arr, size = 5) => {\n  const min = Math.min(...arr);\n  const max = Math.max(...arr);\n  const buckets = Array.from(\n    { length: Math.floor((max - min) / size) + 1 },\n    () => []\n  );\n  arr.forEach(val => {\n    buckets[Math.floor((val - min) / size)].push(val);\n  });\n  return buckets.reduce((acc, b) => [...acc, ...b.sort((a, b) => a - b)], []);\n};",
    "description": "Sorts an array of numbers, using the bucket sort algorithm.\n\n- Use `Math.min(),` `Math.max()` and the spread operator (`...`) to find the minimum and maximum values of the given array.\n- Use `Array.from()` and `Math.floor()` to create the appropriate number of `buckets` (empty arrays).\n- Use `Array.prototype.forEach()` to populate each bucket with the appropriate elements from the array.\n- Use `Array.prototype.reduce()`, the spread operator (`...`) and `Array.prototype.sort()` to sort each bucket and append it to the result.",
    "example": "bucketSort([6, 3, 4, 1]); // [1, 3, 4, 6]",
    "id": "bucketSort",
    "tags": [
      "algorithm",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const byteSize = str => new Blob([str]).size;",
    "description": "Returns the length of a string in bytes.\n\n- Convert a given string to a [`Blob` Object](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n- Use `Blob.size` to get the length of the string in bytes.",
    "example": "byteSize('😀'); // 4\nbyteSize('Hello World'); // 11",
    "id": "byteSize",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const caesarCipher = (str, shift, decrypt = false) => {\n  const s = decrypt ? (26 - shift) % 26 : shift;\n  const n = s > 0 ? s : 26 + (s % 26);\n  return [...str]\n    .map((l, i) => {\n      const c = str.charCodeAt(i);\n      if (c >= 65 && c <= 90)\n        return String.fromCharCode(((c - 65 + n) % 26) + 65);\n      if (c >= 97 && c <= 122)\n        return String.fromCharCode(((c - 97 + n) % 26) + 97);\n      return l;\n    })\n    .join('');\n};",
    "description": "Encrypts or decrypts a given string using the Caesar cipher.\n\n- Use the modulo (`%`) operator and the ternary operator (`?`) to calculate the correct encryption/decryption key.\n- Use the spread operator (`...`) and `Array.prototype.map()` to iterate over the letters of the given string.\n- Use `String.prototype.charCodeAt()` and `String.fromCharCode()` to convert each letter appropriately, ignoring special characters, spaces etc.\n- Use `Array.prototype.join()` to combine all the letters into a string.\n- Pass `true` to the last parameter, `decrypt`, to decrypt an encrypted string.",
    "example": "caesarCipher('Hello World!', -3); // 'Ebiil Tloia!'\ncaesarCipher('Ebiil Tloia!', 23, true); // 'Hello World!'",
    "id": "caesarCipher",
    "tags": [
      "algorithm",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const call = (key, ...args) => context => context[key](...args);",
    "description": "Given a key and a set of arguments, call them when given a context.\n\n- Use a closure to call `key` with `args` for the given `context`.",
    "example": "Promise.resolve([1, 2, 3])\n  .then(call('map', x => 2 * x))\n  .then(console.log); // [ 2, 4, 6 ]\nconst map = call.bind(null, 'map');\nPromise.resolve([1, 2, 3])\n  .then(map(x => 2 * x))\n  .then(console.log); // [ 2, 4, 6 ]",
    "id": "call",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const capitalize = ([first, ...rest], lowerRest = false) =>\n  first.toUpperCase() +\n  (lowerRest ? rest.join('').toLowerCase() : rest.join(''));",
    "description": "Capitalizes the first letter of a string.\n\n- Use array destructuring and `String.prototype.toUpperCase()` to capitalize the first letter of the string.\n- Use `Array.prototype.join('')` to combine the capitalized `first` with the `...rest` of the characters.\n- Omit the `lowerRest` argument to keep the rest of the string intact, or set it to `true` to convert to lowercase.",
    "example": "capitalize('fooBar'); // 'FooBar'\ncapitalize('fooBar', true); // 'Foobar'",
    "id": "capitalize",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const capitalizeEveryWord = str =>\n  str.replace(/\\b[a-z]/g, char => char.toUpperCase());",
    "description": "Capitalizes the first letter of every word in a string.\n\n- Use `String.prototype.replace()` to match the first character of each word and `String.prototype.toUpperCase()` to capitalize it.",
    "example": "capitalizeEveryWord('hello world!'); // 'Hello World!'",
    "id": "capitalizeEveryWord",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const cartesianProduct = (a, b) =>\n  a.reduce((p, x) => [...p, ...b.map(y => [x, y])], []);",
    "description": "Calculates the cartesian product of two arrays.\n\n- Use `Array.prototype.reduce()`, `Array.prototype.map()` and the spread operator (`...`) to generate all possible element pairs from the two arrays.",
    "example": "cartesianProduct(['x', 'y'], [1, 2]);\n// [['x', 1], ['x', 2], ['y', 1], ['y', 2]]",
    "id": "cartesianProduct",
    "tags": [
      "math",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const castArray = val => (Array.isArray(val) ? val : [val]);",
    "description": "Casts the provided value as an array if it's not one.\n\n- Use `Array.prototype.isArray()` to determine if `val` is an array and return it as-is or encapsulated in an array accordingly.",
    "example": "castArray('foo'); // ['foo']\ncastArray([1]); // [1]",
    "id": "castArray",
    "tags": [
      "type",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;",
    "description": "Converts Celsius to Fahrenheit.\n\n- Follow the conversion formula `F = 1.8 * C + 32`.",
    "example": "celsiusToFahrenheit(33); // 91.4",
    "id": "celsiusToFahrenheit",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const chainAsync = fns => {\n  let curr = 0;\n  const last = fns[fns.length - 1];\n  const next = () => {\n    const fn = fns[curr++];\n    fn === last ? fn() : fn(next);\n  };\n  next();\n};",
    "description": "Chains asynchronous functions.\n\n- Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed.",
    "example": "chainAsync([\n  next => {\n    console.log('0 seconds');\n    setTimeout(next, 1000);\n  },\n  next => {\n    console.log('1 second');\n    setTimeout(next, 1000);\n  },\n  () => {\n    console.log('2 second');\n  }\n]);",
    "id": "chainAsync",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const changeLightness = (delta, hslStr) => {\n  const [hue, saturation, lightness] = hslStr.match(/\\d+/g).map(Number);\n\n  const newLightness = Math.max(\n    0,\n    Math.min(100, lightness + parseFloat(delta))\n  );\n\n  return \\`hsl(\\${hue}, \\${saturation}%, \\${newLightness}%)\\`;\n};",
    "description": "Changes the lightness value of an `hsl()` color string.\n\n- Use `String.prototype.match()` to get an array of 3 strings with the numeric values.\n- Use `Array.prototype.map()` in combination with `Number` to convert them into an array of numeric values.\n- Make sure the lightness is within the valid range (between `0` and `100`), using `Math.max()` and `Math.min()`.\n- Use a template literal to create a new `hsl()` string with the updated value.",
    "example": "changeLightness(10, 'hsl(330, 50%, 50%)'); // 'hsl(330, 50%, 60%)'\nchangeLightness(-10, 'hsl(330, 50%, 50%)'); // 'hsl(330, 50%, 40%)'",
    "id": "changeLightness",
    "tags": [
      "string",
      "browser",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]);",
    "description": "Creates a function that will invoke a predicate function for the specified property on a given object.\n\n- Return a curried function, that will invoke `predicate` for the specified `prop` on `obj` and return a boolean.",
    "example": "const lengthIs4 = checkProp(l => l === 4, 'length');\nlengthIs4([]); // false\nlengthIs4([1, 2, 3, 4]); // true\nlengthIs4(new Set([1, 2, 3, 4])); // false (Set uses Size, not length)\n\nconst session = { user: {} };\nconst validUserSession = checkProp(u => u.active && !u.disabled, 'user');\n\nvalidUserSession(session); // false\n\nsession.user.active = true;\nvalidUserSession(session); // true\n\nconst noLength = checkProp(l => l === undefined, 'length');\nnoLength([]); // false\nnoLength({}); // true\nnoLength(new Set()); // true",
    "id": "checkProp",
    "tags": [
      "function",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const chunk = (arr, size) =>\n  Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>\n    arr.slice(i * size, i * size + size)\n  );",
    "description": "Chunks an array into smaller arrays of a specified size.\n\n- Use `Array.from()` to create a new array, that fits the number of chunks that will be produced.\n- Use `Array.prototype.slice()` to map each element of the new array to a chunk the length of `size`.\n- If the original array can't be split evenly, the final chunk will contain the remaining elements.",
    "example": "chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]",
    "id": "chunk",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const chunkIntoN = (arr, n) => {\n  const size = Math.ceil(arr.length / n);\n  return Array.from({ length: n }, (v, i) =>\n    arr.slice(i * size, i * size + size)\n  );\n}",
    "description": "Chunks an array into `n` smaller arrays.\n\n- Use `Math.ceil()` and `Array.prototype.length` to get the size of each chunk.\n- Use `Array.from()` to create a new array of size `n`.\n- Use `Array.prototype.slice()` to map each element of the new array to a chunk the length of `size`.\n- If the original array can't be split evenly, the final chunk will contain the remaining elements.",
    "example": "chunkIntoN([1, 2, 3, 4, 5, 6, 7], 4); // [[1, 2], [3, 4], [5, 6], [7]]",
    "id": "chunkIntoN",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const chunkify = function* (itr, size) {\n  let chunk = [];\n  for (const v of itr) {\n    chunk.push(v);\n    if (chunk.length === size) {\n      yield chunk;\n      chunk = [];\n    }\n  }\n  if (chunk.length) yield chunk;\n};",
    "description": "Chunks an iterable into smaller arrays of a specified size.\n\n- Use a `for...of` loop over the given iterable, using `Array.prototype.push()` to add each new value to the current `chunk`.\n- Use `Array.prototype.length` to check if the current `chunk` is of the desired `size` and `yield` the value if it is.\n- Finally, use `Array.prototype.length` to check the final `chunk` and `yield` it if it's non-empty.",
    "example": "const x = new Set([1, 2, 1, 3, 4, 1, 2, 5]);\n[...chunkify(x, 2)]; // [[1, 2], [3, 4], [5]]",
    "id": "chunkify",
    "tags": [
      "function",
      "generator",
      "array",
      "advanced"
    ]
  },
  {
    "code": "const clampNumber = (num, a, b) =>\n  Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));",
    "description": "Clamps `num` within the inclusive range specified by the boundary values `a` and `b`.\n\n- If `num` falls within the range, return `num`.\n- Otherwise, return the nearest number in the range.",
    "example": "clampNumber(2, 3, 5); // 3\nclampNumber(1, -1, -5); // -1",
    "id": "clampNumber",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);",
    "description": "Clones a regular expression.\n\n- Use `new RegExp()`, `RegExp.prototype.source` and `RegExp.prototype.flags` to clone the given regular expression.",
    "example": "const regExp = /lorem ipsum/gi;\nconst regExp2 = cloneRegExp(regExp); // regExp !== regExp2",
    "id": "cloneRegExp",
    "tags": [
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const coalesce = (...args) => args.find(v => ![undefined, null].includes(v));",
    "description": "Returns the first defined, non-null argument.\n\n- Use `Array.prototype.find()` and `Array.prototype.includes()` to find the first value that is not equal to `undefined` or `null`.",
    "example": "coalesce(null, undefined, '', NaN, 'Waldo'); // ''",
    "id": "coalesce",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const coalesceFactory = valid => (...args) => args.find(valid);",
    "description": "Customizes a coalesce function that returns the first argument which is true based on the given validator.\n\n- Use `Array.prototype.find()` to return the first argument that returns `true` from the provided argument validation function, `valid`.",
    "example": "const customCoalesce = coalesceFactory(\n  v => ![null, undefined, '', NaN].includes(v)\n);\ncustomCoalesce(undefined, null, NaN, '', 'Waldo'); // 'Waldo'",
    "id": "coalesceFactory",
    "tags": [
      "function",
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const collectInto = fn => (...args) => fn(args);",
    "description": "Changes a function that accepts an array into a variadic function.\n\n- Given a function, return a closure that collects all inputs into an array-accepting function.",
    "example": "const Pall = collectInto(Promise.all.bind(Promise));\nlet p1 = Promise.resolve(1);\nlet p2 = Promise.resolve(2);\nlet p3 = new Promise(resolve => setTimeout(resolve, 2000, 3));\nPall(p1, p2, p3).then(console.log); // [1, 2, 3] (after about 2 seconds)",
    "id": "collectInto",
    "tags": [
      "function",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const colorize = (...args) => ({\n  black: \\`\\x1b[30m\\${args.join(' ')}\\`,\n  red: \\`\\x1b[31m\\${args.join(' ')}\\`,\n  green: \\`\\x1b[32m\\${args.join(' ')}\\`,\n  yellow: \\`\\x1b[33m\\${args.join(' ')}\\`,\n  blue: \\`\\x1b[34m\\${args.join(' ')}\\`,\n  magenta: \\`\\x1b[35m\\${args.join(' ')}\\`,\n  cyan: \\`\\x1b[36m\\${args.join(' ')}\\`,\n  white: \\`\\x1b[37m\\${args.join(' ')}\\`,\n  bgBlack: \\`\\x1b[40m\\${args.join(' ')}\\x1b[0m\\`,\n  bgRed: \\`\\x1b[41m\\${args.join(' ')}\\x1b[0m\\`,\n  bgGreen: \\`\\x1b[42m\\${args.join(' ')}\\x1b[0m\\`,\n  bgYellow: \\`\\x1b[43m\\${args.join(' ')}\\x1b[0m\\`,\n  bgBlue: \\`\\x1b[44m\\${args.join(' ')}\\x1b[0m\\`,\n  bgMagenta: \\`\\x1b[45m\\${args.join(' ')}\\x1b[0m\\`,\n  bgCyan: \\`\\x1b[46m\\${args.join(' ')}\\x1b[0m\\`,\n  bgWhite: \\`\\x1b[47m\\${args.join(' ')}\\x1b[0m\\`\n});",
    "description": "Adds special characters to text to print in color in the console (combined with `console.log()`).\n\n- Use template literals and special characters to add the appropriate color code to the string output.\n- For background colors, add a special character that resets the background color at the end of the string.",
    "example": "console.log(colorize('foo').red); // 'foo' (red letters)\nconsole.log(colorize('foo', 'bar').bgBlue); // 'foo bar' (blue background)\nconsole.log(colorize(colorize('foo').yellow, colorize('foo').green).bgWhite);\n// 'foo bar' (first word in yellow letters, second word in green letters, white background for both)",
    "id": "colorize",
    "tags": [
      "node",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const combine = (a, b, prop) =>\n  Object.values(\n    [...a, ...b].reduce((acc, v) => {\n      if (v[prop])\n        acc[v[prop]] = acc[v[prop]]\n          ? { ...acc[v[prop]], ...v }\n          : { ...v };\n      return acc;\n    }, {})\n  );",
    "description": "Combines two arrays of objects, using the specified key to match objects.\n\n- Use `Array.prototype.reduce()` with an object accumulator to combine all objects in both arrays based on the given `prop`.\n- Use `Object.values()` to convert the resulting object to an array and return it.",
    "example": "const x = [\n  { id: 1, name: 'John' },\n  { id: 2, name: 'Maria' }\n];\nconst y = [\n  { id: 1, age: 28 },\n  { id: 3, age: 26 },\n  { age: 3}\n];\ncombine(x, y, 'id');\n// [\n//  { id: 1, name: 'John', age: 28 },\n//  { id: 2, name: 'Maria' },\n//  { id: 3, age: 26 }\n// ]",
    "id": "combine",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const compact = arr => arr.filter(Boolean);",
    "description": "Removes falsy values from an array.\n\n- Use `Array.prototype.filter()` to filter out falsy values (`false`, `null`, `0`, `\"\"`, `undefined`, and `NaN`).",
    "example": "compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); \n// [ 1, 2, 3, 'a', 's', 34 ]",
    "id": "compact",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const compactObject = val => {\n  const data = Array.isArray(val) ? val.filter(Boolean) : val;\n  return Object.keys(data).reduce(\n    (acc, key) => {\n      const value = data[key];\n      if (Boolean(value))\n        acc[key] = typeof value === 'object' ? compactObject(value) : value;\n      return acc;\n    },\n    Array.isArray(val) ? [] : {}\n  );\n};",
    "description": "Deeply removes all falsy values from an object or array.\n\n- Use recursion.\n- Initialize the iterable data, using `Array.isArray()`, `Array.prototype.filter()` and `Boolean` for arrays in order to avoid sparse arrays.\n- Use `Object.keys()` and `Array.prototype.reduce()` to iterate over each key with an appropriate initial value.\n- Use `Boolean` to determine the truthiness of each key's value and add it to the accumulator if it's truthy.\n- Use `typeof` to determine if a given value is an `object` and call the function again to deeply compact it.",
    "example": "const obj = {\n  a: null,\n  b: false,\n  c: true,\n  d: 0,\n  e: 1,\n  f: '',\n  g: 'a',\n  h: [null, false, '', true, 1, 'a'],\n  i: { j: 0, k: false, l: 'a' }\n};\ncompactObject(obj);\n// { c: true, e: 1, g: 'a', h: [ true, 1, 'a' ], i: { l: 'a' } }",
    "id": "compactObject",
    "tags": [
      "object",
      "array",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const compactWhitespace = str => str.replace(/\\s{2,}/g, ' ');",
    "description": "Compacts whitespaces in a string.\n\n- Use `String.prototype.replace()` with a regular expression to replace all occurrences of 2 or more whitespace characters with a single space.",
    "example": "compactWhitespace('Lorem    Ipsum'); // 'Lorem Ipsum'\ncompactWhitespace('Lorem \\n Ipsum'); // 'Lorem Ipsum'",
    "id": "compactWhitespace",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const complement = fn => (...args) => !fn(...args);",
    "description": "Returns a function that is the logical complement of the given function, `fn`.\n\n- Use the logical not (`!`) operator on the result of calling `fn` with any supplied `args`.",
    "example": "const isEven = num => num % 2 === 0;\nconst isOdd = complement(isEven);\nisOdd(2); // false\nisOdd(3); // true",
    "id": "complement",
    "tags": [
      "function",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const compose = (...fns) =>\n  fns.reduce((f, g) => (...args) => f(g(...args)));",
    "description": "Performs right-to-left function composition.\n\n- Use `Array.prototype.reduce()` to perform right-to-left function composition.\n- The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.",
    "example": "const add5 = x => x + 5;\nconst multiply = (x, y) => x * y;\nconst multiplyAndAdd5 = compose(\n  add5,\n  multiply\n);\nmultiplyAndAdd5(5, 2); // 15",
    "id": "compose",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const composeRight = (...fns) =>\n  fns.reduce((f, g) => (...args) => g(f(...args)));",
    "description": "Performs left-to-right function composition.\n\n- Use `Array.prototype.reduce()` to perform left-to-right function composition.\n- The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.",
    "example": "const add = (x, y) => x + y;\nconst square = x => x * x;\nconst addAndSquare = composeRight(add, square);\naddAndSquare(1, 2); // 9",
    "id": "composeRight",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const containsWhitespace = str => /\\s/.test(str);",
    "description": "Checks if the given string contains any whitespace characters.\n\n- Use `RegExp.prototype.test()` with an appropriate regular expression to check if the given string contains any whitespace characters.",
    "example": "containsWhitespace('lorem'); // false\ncontainsWhitespace('lorem ipsum'); // true",
    "id": "containsWhitespace",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const converge = (converger, fns) => (...args) =>\n  converger(...fns.map(fn => fn.apply(null, args)));",
    "description": "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.\n\n- Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments.\n- Use the spread operator (`...`) to call `converger` with the results of all other functions.",
    "example": "const average = converge((a, b) => a / b, [\n  arr => arr.reduce((a, v) => a + v, 0),\n  arr => arr.length\n]);\naverage([1, 2, 3, 4, 5, 6, 7]); // 4",
    "id": "converge",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const copySign = (x, y) => Math.sign(x) === Math.sign(y) ? x : -x;",
    "description": "Returns the absolute value of the first number, but the sign of the second.\n\n- Use `Math.sign()` to check if the two numbers have the same sign.\n- Return `x` if they do, `-x` otherwise.",
    "example": "copySign(2, 3); // 2\ncopySign(2, -3); // -2\ncopySign(-2, 3); // 2\ncopySign(-2, -3); // -2",
    "id": "copySign",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const copyToClipboard = str => {\n  const el = document.createElement('textarea');\n  el.value = str;\n  el.setAttribute('readonly', '');\n  el.style.position = 'absolute';\n  el.style.left = '-9999px';\n  document.body.appendChild(el);\n  const selected =\n    document.getSelection().rangeCount > 0\n      ? document.getSelection().getRangeAt(0)\n      : false;\n  el.select();\n  document.execCommand('copy');\n  document.body.removeChild(el);\n  if (selected) {\n    document.getSelection().removeAllRanges();\n    document.getSelection().addRange(selected);\n  }\n};",
    "description": "Copies a string to the clipboard.\nOnly works as a result of user action (i.e. inside a `click` event listener).\n\n- Create a new `<textarea>` element, fill it with the supplied data and add it to the HTML document.\n- Use `Selection.getRangeAt()`to store the selected range (if any).\n- Use `Document.execCommand('copy')` to copy to the clipboard.\n- Remove the `<textarea>` element from the HTML document.\n- Finally, use `Selection().addRange()` to recover the original selected range (if any).\n- **Note:** You can use the new asynchronous Clipboard API to implement the same functionality. It's experimental but should be used in the future instead of this snippet. Find out more about it [here](https://github.com/w3c/clipboard-apis/blob/master/explainer.adoc#writing-to-the-clipboard).",
    "example": "copyToClipboard('Lorem ipsum'); // 'Lorem ipsum' copied to clipboard.",
    "id": "copyToClipboard",
    "tags": [
      "browser",
      "string",
      "event",
      "advanced"
    ]
  },
  {
    "code": "const countBy = (arr, fn) =>\n  arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {\n    acc[val] = (acc[val] || 0) + 1;\n    return acc;\n  }, {});",
    "description": "Groups the elements of an array based on the given function and returns the count of elements in each group.\n\n- Use `Array.prototype.map()` to map the values of an array to a function or property name.\n- Use `Array.prototype.reduce()` to create an object, where the keys are produced from the mapped results.",
    "example": "countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2}\ncountBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1}\ncountBy([{ count: 5 }, { count: 10 }, { count: 5 }], x => x.count)\n// {5: 2, 10: 1}",
    "id": "countBy",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const countOccurrences = (arr, val) =>\n  arr.reduce((a, v) => (v === val ? a + 1 : a), 0);",
    "description": "Counts the occurrences of a value in an array.\n\n- Use `Array.prototype.reduce()` to increment a counter each time the specific value is encountered inside the array.",
    "example": "countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3",
    "id": "countOccurrences",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const countSubstrings = (str, searchValue) => {\n  let count = 0,\n    i = 0;\n  while (true) {\n    const r = str.indexOf(searchValue, i);\n    if (r !== -1) [count, i] = [count + 1, r + 1];\n    else return count;\n  }\n};",
    "description": "Counts the occurrences of a substring in a given string.\n\n- Use `Array.prototype.indexOf()` to look for `searchValue` in `str`.\n- Increment a counter if the value is found and update the index, `i`.\n- Use a `while` loop that will return as soon as the value returned from `Array.prototype.indexOf()` is `-1`.",
    "example": "countSubstrings('tiktok tok tok tik tok tik', 'tik'); // 3\ncountSubstrings('tutut tut tut', 'tut'); // 4",
    "id": "countSubstrings",
    "tags": [
      "string",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const countWeekDaysBetween = (startDate, endDate) =>\n  Array\n    .from({ length: (endDate - startDate) / (1000 * 3600 * 24) })\n    .reduce(count => {\n      if (startDate.getDay() % 6 !== 0) count++;\n      startDate = new Date(startDate.setDate(startDate.getDate() + 1));\n      return count;\n    }, 0);",
    "description": "Counts the weekdays between two dates.\n\n- Use `Array.from()` to construct an array with `length` equal to the number of days between `startDate` and `endDate`.\n- Use `Array.prototype.reduce()` to iterate over the array, checking if each date is a weekday and incrementing `count`.\n- Update `startDate` with the next day each loop using `Date.prototype.getDate()` and `Date.prototype.setDate()` to advance it by one day.\n- **NOTE:** Does not take official holidays into account.",
    "example": "countWeekDaysBetween(new Date('Oct 05, 2020'), new Date('Oct 06, 2020')); // 1\ncountWeekDaysBetween(new Date('Oct 05, 2020'), new Date('Oct 14, 2020')); // 7",
    "id": "countWeekDaysBetween",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const counter = (selector, start, end, step = 1, duration = 2000) => {\n  let current = start,\n    _step = (end - start) * step < 0 ? -step : step,\n    timer = setInterval(() => {\n      current += _step;\n      document.querySelector(selector).innerHTML = current;\n      if (current >= end) document.querySelector(selector).innerHTML = end;\n      if (current >= end) clearInterval(timer);\n    }, Math.abs(Math.floor(duration / (end - start))));\n  return timer;\n};",
    "description": "Creates a counter with the specified range, step and duration for the specified selector.\n\n- Check if `step` has the proper sign and change it accordingly.\n- Use `setInterval()` in combination with `Math.abs()` and `Math.floor()` to calculate the time between each new text draw.\n- Use `Document.querySelector()`, `Element.innerHTML` to update the value of the selected element.\n- Omit the fourth argument, `step`, to use a default step of `1`.\n- Omit the fifth argument, `duration`, to use a default duration of `2000`ms.",
    "example": "counter('#my-id', 1, 1000, 5, 2000);\n// Creates a 2-second timer for the element with id=\"my-id\"",
    "id": "counter",
    "tags": [
      "browser",
      "advanced"
    ]
  },
  {
    "code": "const fs = require('fs');\n\nconst createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);",
    "description": "Creates a directory, if it does not exist.\n\n- Use `fs.existsSync()` to check if the directory exists, `fs.mkdirSync()` to create it.",
    "example": "createDirIfNotExists('test');\n// creates the directory 'test', if it doesn't exist",
    "id": "createDirIfNotExists",
    "tags": [
      "node",
      "beginner"
    ]
  },
  {
    "code": "const createElement = str => {\n  const el = document.createElement('div');\n  el.innerHTML = str;\n  return el.firstElementChild;\n};",
    "description": "Creates an element from a string (without appending it to the document).\nIf the given string contains multiple elements, only the first one will be returned.\n\n- Use `Document.createElement()` to create a new element.\n- Use `Element.innerHTML` to set its inner HTML to the string supplied as the argument.\n- Use `ParentNode.firstElementChild` to return the element version of the string.",
    "example": "const el = createElement(\n  `<div class=\"container\">\n    <p>Hello!</p>\n  </div>`\n);\nconsole.log(el.className); // 'container'",
    "id": "createElement",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const createEventHub = () => ({\n  hub: Object.create(null),\n  emit(event, data) {\n    (this.hub[event] || []).forEach(handler => handler(data));\n  },\n  on(event, handler) {\n    if (!this.hub[event]) this.hub[event] = [];\n    this.hub[event].push(handler);\n  },\n  off(event, handler) {\n    const i = (this.hub[event] || []).findIndex(h => h === handler);\n    if (i > -1) this.hub[event].splice(i, 1);\n    if (this.hub[event].length === 0) delete this.hub[event];\n  }\n});",
    "description": "Creates a pub/sub ([publish–subscribe](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern)) event hub with `emit`, `on`, and `off` methods.\n\n- Use `Object.create(null)` to create an empty `hub` object that does not inherit properties from `Object.prototype`.\n- 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.\n- For `on`, create an array for the event if it does not yet exist, then use `Array.prototype.push()` to add the handler\n- to the array.\n- For `off`, use `Array.prototype.findIndex()` to find the index of the handler in the event array and remove it using `Array.prototype.splice()`.",
    "example": "const handler = data => console.log(data);\nconst hub = createEventHub();\nlet increment = 0;\n\n// Subscribe: listen for different types of events\nhub.on('message', handler);\nhub.on('message', () => console.log('Message event fired'));\nhub.on('increment', () => increment++);\n\n// Publish: emit events to invoke all handlers subscribed to them, passing the data to them as an argument\nhub.emit('message', 'hello world'); // logs 'hello world' and 'Message event fired'\nhub.emit('message', { hello: 'world' }); // logs the object and 'Message event fired'\nhub.emit('increment'); // `increment` variable is now 1\n\n// Unsubscribe: stop a specific handler from listening to the 'message' event\nhub.off('message', handler);",
    "id": "createEventHub",
    "tags": [
      "browser",
      "event",
      "advanced"
    ]
  },
  {
    "code": "const currentURL = () => window.location.href;",
    "description": "Returns the current URL.\n\n- Use `Window.location.href` to get the current URL.",
    "example": "currentURL(); // 'https://www.google.com/'",
    "id": "currentURL",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const curry = (fn, arity = fn.length, ...args) =>\n  arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);",
    "description": "Curries a function.\n\n- Use recursion.\n- If the number of provided arguments (`args`) is sufficient, call the passed function `fn`.\n- Otherwise, use `Function.prototype.bind()` to return a curried function `fn` that expects the rest of the arguments.\n- 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`.",
    "example": "curry(Math.pow)(2)(10); // 1024\ncurry(Math.min, 3)(10)(50)(2); // 2",
    "id": "curry",
    "tags": [
      "function",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const cycleGenerator = function* (arr) {\n  let i = 0;\n  while (true) {\n    yield arr[i % arr.length];\n    i++;\n  }\n};",
    "description": "Creates a generator, looping over the given array indefinitely.\n\n- Use a non-terminating `while` loop, that will `yield` a value every time `Generator.prototype.next()` is called.\n- Use the module operator (`%`) with `Array.prototype.length` to get the next value's index and increment the counter after each `yield` statement.",
    "example": "const binaryCycle = cycleGenerator([0, 1]);\nbinaryCycle.next(); // { value: 0, done: false }\nbinaryCycle.next(); // { value: 1, done: false }\nbinaryCycle.next(); // { value: 0, done: false }\nbinaryCycle.next(); // { value: 1, done: false }",
    "id": "cycleGenerator",
    "tags": [
      "function",
      "generator",
      "advanced"
    ]
  },
  {
    "code": "const dateRangeGenerator = function* (start, end, step = 1) {\n  let d = start;\n  while (d < end) {\n    yield new Date(d);\n    d.setDate(d.getDate() + step);\n  }\n};",
    "description": "Creates a generator, that generates all dates in the given range using the given step.\n\n- Use a `while` loop to iterate from `start` to `end`, using `yield` to return each date in the range, using the `Date` constructor.\n- Use `Date.prototype.getDate()` and `Date.prototype.setDate()` to increment by `step` days after returning each subsequent value.\n- Omit the third argument, `step`, to use a default value of `1`.",
    "example": "[...dateRangeGenerator(new Date('2021-06-01'), new Date('2021-06-04'))];\n// [ 2021-06-01, 2021-06-02, 2021-06-03 ]",
    "id": "dateRangeGenerator",
    "tags": [
      "date",
      "function",
      "generator",
      "advanced"
    ]
  },
  {
    "code": "const dayName = (date, locale) =>\n  date.toLocaleDateString(locale, { weekday: 'long' });",
    "description": "Gets the name of the weekday from a `Date` object.\n\n- Use `Date.prototype.toLocaleDateString()` with the `{ weekday: 'long' }` option to retrieve the weekday.\n- Use the optional second argument to get a language-specific name or omit it to use the default locale.",
    "example": "dayName(new Date()); // 'Saturday'\ndayName(new Date('09/23/2020'), 'de-DE'); // 'Samstag'",
    "id": "dayName",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const dayOfYear = date =>\n  Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);",
    "description": "Gets the day of the year (number in the range 1-366) from a `Date` object.\n\n- Use `new Date()` and `Date.prototype.getFullYear()` to get the first day of the year as a `Date` object.\n- Subtract the first day of the year from `date` and divide with the milliseconds in each day to get the result.\n- Use `Math.floor()` to appropriately round the resulting day count to an integer.",
    "example": "dayOfYear(new Date()); // 272",
    "id": "dayOfYear",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const daysAgo = n => {\n  let d = new Date();\n  d.setDate(d.getDate() - Math.abs(n));\n  return d.toISOString().split('T')[0];\n};",
    "description": "Calculates the date of `n` days ago from today as a string representation.\n\n- Use `new Date()` to get the current date, `Math.abs()` and `Date.prototype.getDate()` to update the date accordingly and set to the result using `Date.prototype.setDate()`.\n- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.",
    "example": "daysAgo(20); // 2020-09-16 (if current date is 2020-10-06)",
    "id": "daysAgo",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const daysFromNow = n => {\n  let d = new Date();\n  d.setDate(d.getDate() + Math.abs(n));\n  return d.toISOString().split('T')[0];\n};",
    "description": "Calculates the date of `n` days from today as a string representation.\n\n- Use `new Date()` to get the current date, `Math.abs()` and `Date.prototype.getDate()` to update the date accordingly and set to the result using `Date.prototype.setDate()`.\n- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.",
    "example": "daysFromNow(5); // 2020-10-13 (if current date is 2020-10-08)",
    "id": "daysFromNow",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const daysInMonth = (year, month) => new Date(year, month, 0).getDate();",
    "description": "Gets the number of days in the given `month` of the specified `year`.\n\n- Use the `new Date()` constructor to create a date from the given `year` and `month`.\n- Set the days parameter to `0` to get the last day of the previous month, as months are zero-indexed.\n- Use `Date.prototype.getDate()` to return the number of days in the given `month`.",
    "example": "daysInMonth(2020, 12)); // 31\ndaysInMonth(2024, 2)); // 29",
    "id": "daysInMonth",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const debounce = (fn, ms = 0) => {\n  let timeoutId;\n  return function(...args) {\n    clearTimeout(timeoutId);\n    timeoutId = setTimeout(() => fn.apply(this, args), ms);\n  };\n};",
    "description": "Creates a debounced function that delays invoking the provided function until at least `ms` milliseconds have elapsed since its last invocation.\n\n- 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.\n- Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary arguments.\n- Omit the second argument, `ms`, to set the timeout at a default of `0` ms.",
    "example": "window.addEventListener(\n  'resize',\n  debounce(() => {\n    console.log(window.innerWidth);\n    console.log(window.innerHeight);\n  }, 250)\n); // Will log the window dimensions at most every 250ms",
    "id": "debounce",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const debouncePromise = (fn, ms = 0) => {\n  let timeoutId;\n  const pending = [];\n  return (...args) =>\n    new Promise((res, rej) => {\n      clearTimeout(timeoutId);\n      timeoutId = setTimeout(() => {\n        const currentPending = [...pending];\n        pending.length = 0;\n        Promise.resolve(fn.apply(this, args)).then(\n          data => {\n            currentPending.forEach(({ resolve }) => resolve(data));\n          },\n          error => {\n            currentPending.forEach(({ reject }) => reject(error));\n          }\n        );\n      }, ms);\n      pending.push({ resolve: res, reject: rej });\n    });\n};",
    "description": "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. \nAll promises returned during this time will return the same data.\n\n- 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.\n- Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary arguments.\n- Create a new `Promise` and add its `resolve` and `reject` callbacks to the `pending` promises stack.\n- 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.\n- When the provided function resolves/rejects, resolve/reject all promises in the stack (copied when the function was called) with the returned data.\n- Omit the second argument, `ms`, to set the timeout at a default of `0` ms.",
    "example": "const fn = arg => new Promise(resolve => {\n  setTimeout(resolve, 1000, ['resolved', arg]);\n});\nconst debounced = debouncePromise(fn, 200);\ndebounced('foo').then(console.log);\ndebounced('bar').then(console.log);\n// Will log ['resolved', 'bar'] both times",
    "id": "debouncePromise",
    "tags": [
      "function",
      "promise",
      "advanced"
    ]
  },
  {
    "code": "const decapitalize = ([first, ...rest], upperRest = false) =>\n  first.toLowerCase() +\n  (upperRest ? rest.join('').toUpperCase() : rest.join(''));",
    "description": "Decapitalizes the first letter of a string.\n\n- 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.\n- Omit the `upperRest` argument to keep the rest of the string intact, or set it to `true` to convert to uppercase.",
    "example": "decapitalize('FooBar'); // 'fooBar'\ndecapitalize('FooBar', true); // 'fOOBAR'",
    "id": "decapitalize",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const deepClone = obj => {\n  if (obj === null) return null;\n  let clone = Object.assign({}, obj);\n  Object.keys(clone).forEach(\n    key =>\n      (clone[key] =\n        typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])\n  );\n  if (Array.isArray(obj)) {\n    clone.length = obj.length;\n    return Array.from(clone);\n  }\n  return clone;\n};",
    "description": "Creates a deep clone of an object. \nClones primitives, arrays and objects, excluding class instances.\n\n- Use recursion.\n- Check if the passed object is `null` and, if so, return `null`.\n- Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original.\n- Use `Object.keys()` and `Array.prototype.forEach()` to determine which key-value pairs need to be deep cloned.\n- If the object is an `Array`, set the `clone`'s `length` to that of the original and use `Array.from(clone)` to create a clone.",
    "example": "const a = { foo: 'bar', obj: { a: 1, b: 2 } };\nconst b = deepClone(a); // a !== b, a.obj !== b.obj",
    "id": "deepClone",
    "tags": [
      "object",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const deepFlatten = arr =>\n  [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));",
    "description": "Deep flattens an array.\n\n- Use recursion.\n- Use `Array.prototype.concat()` with an empty array (`[]`) and the spread operator (`...`) to flatten an array.\n- Recursively flatten each element that is an array.",
    "example": "deepFlatten([1, [2], [[3], 4], 5]); // [1, 2, 3, 4, 5]",
    "id": "deepFlatten",
    "tags": [
      "array",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const deepFreeze = obj => {\n  Object.keys(obj).forEach(prop => {\n    if (typeof obj[prop] === 'object') deepFreeze(obj[prop]);\n  });\n  return Object.freeze(obj);\n};",
    "description": "Deep freezes an object.\n\n- Use `Object.keys()` to get all the properties of the passed object, `Array.prototype.forEach()` to iterate over them.\n- Call `Object.freeze(obj)` recursively on all properties, applying `deepFreeze()` as necessary.\n- Finally, use `Object.freeze()` to freeze the given object.",
    "example": "'use strict';\n\nconst val = deepFreeze([1, [2, 3]]);\n\nval[0] = 3; // not allowed\nval[1][0] = 4; // not allowed as well",
    "id": "deepFreeze",
    "tags": [
      "object",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const deepGet = (obj, keys) =>\n  keys.reduce(\n    (xs, x) => (xs && xs[x] !== null && xs[x] !== undefined ? xs[x] : null),\n    obj\n  );",
    "description": "Gets the target value in a nested JSON object, based on the `keys` array.\n\n- Compare the keys you want in the nested JSON object as an `Array`.\n- Use `Array.prototype.reduce()` to get the values in the nested JSON object one by one.\n- If the key exists in the object, return the target value, otherwise return `null`.",
    "example": "let index = 2;\nconst data = {\n  foo: {\n    foz: [1, 2, 3],\n    bar: {\n      baz: ['a', 'b', 'c']\n    }\n  }\n};\ndeepGet(data, ['foo', 'foz', index]); // get 3\ndeepGet(data, ['foo', 'bar', 'baz', 8, 'foz']); // null",
    "id": "deepGet",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const deepMapKeys = (obj, fn) =>\n  Array.isArray(obj)\n    ? obj.map(val => deepMapKeys(val, fn))\n    : typeof obj === 'object'\n    ? Object.keys(obj).reduce((acc, current) => {\n        const key = fn(current);\n        const val = obj[current];\n        acc[key] =\n          val !== null && typeof val === 'object' ? deepMapKeys(val, fn) : val;\n        return acc;\n      }, {})\n    : obj;",
    "description": "Deep maps an object's keys.\n\n- Creates an object with the same values as the provided object and keys generated by running the provided function for each key.\n- Use `Object.keys(obj)` to iterate over the object's keys.\n- Use `Array.prototype.reduce()` to create a new object with the same values and mapped keys using `fn`.",
    "example": "const obj = {\n  foo: '1',\n  nested: {\n    child: {\n      withArray: [\n        {\n          grandChild: ['hello']\n        }\n      ]\n    }\n  }\n};\nconst upperKeysObj = deepMapKeys(obj, key => key.toUpperCase());\n/*\n{\n  \"FOO\":\"1\",\n  \"NESTED\":{\n    \"CHILD\":{\n      \"WITHARRAY\":[\n        {\n          \"GRANDCHILD\":[ 'hello' ]\n        }\n      ]\n    }\n  }\n}\n*/",
    "id": "deepMapKeys",
    "tags": [
      "object",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const deepMerge = (a, b, fn) =>\n  [...new Set([...Object.keys(a), ...Object.keys(b)])].reduce(\n    (acc, key) => ({ ...acc, [key]: fn(key, a[key], b[key]) }),\n    {}\n  );",
    "description": "Deeply merges two objects, using a function to handle keys present in both.\n\n- Use `Object.keys()` to get the keys of both objects, create a `Set` from them and use the spread operator (`...`) to create an array of all the unique keys.\n- Use `Array.prototype.reduce()` to add each unique key to the object, using `fn` to combine the values of the two given objects.",
    "example": "deepMerge(\n  { a: true, b: { c: [1, 2, 3] } },\n  { a: false, b: { d: [1, 2, 3] } },\n  (key, a, b) => (key === 'a' ? a && b : Object.assign({}, a, b))\n);\n// { a: false, b: { c: [ 1, 2, 3 ], d: [ 1, 2, 3 ] } }",
    "id": "deepMerge",
    "tags": [
      "object",
      "function",
      "advanced"
    ]
  },
  {
    "code": "const defaults = (obj, ...defs) =>\n  Object.assign({}, obj, ...defs.reverse(), obj);",
    "description": "Assigns default values for all properties in an object that are `undefined`.\n\n- Use `Object.assign()` to create a new empty object and copy the original one to maintain key order.\n- Use `Array.prototype.reverse()` and the spread operator (`...`) to combine the default values from left to right.\n- Finally, use `obj` again to overwrite properties that originally had a value.",
    "example": "defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 }",
    "id": "defaults",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const defer = (fn, ...args) => setTimeout(fn, 1, ...args);",
    "description": "Defers invoking a function until the current call stack has cleared.\n\n- Use `setTimeout()` with a timeout of `1` ms to add a new event to the event queue and allow the rendering engine to complete its work.\n- Use the spread (`...`) operator to supply the function with an arbitrary number of arguments.",
    "example": "// Example A:\ndefer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'\n\n// Example B:\ndocument.querySelector('#someElement').innerHTML = 'Hello';\nlongRunningFunction();\n// Browser will not update the HTML until this has finished\ndefer(longRunningFunction);\n// Browser will update the HTML then run the function",
    "id": "defer",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const degreesToRads = deg => (deg * Math.PI) / 180.0;",
    "description": "Converts an angle from degrees to radians.\n\n- Use `Math.PI` and the degree to radian formula to convert the angle from degrees to radians.",
    "example": "degreesToRads(90.0); // ~1.5708",
    "id": "degreesToRads",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const delay = (fn, ms, ...args) => setTimeout(fn, ms, ...args);",
    "description": "Invokes the provided function after `ms` milliseconds.\n\n- Use `setTimeout()` to delay execution of `fn`.\n- Use the spread (`...`) operator to supply the function with an arbitrary number of arguments.",
    "example": "delay(\n  function(text) {\n    console.log(text);\n  },\n  1000,\n  'later'\n); // Logs 'later' after one second.",
    "id": "delay",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const detectDeviceType = () =>\n  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n    navigator.userAgent\n  )\n    ? 'Mobile'\n    : 'Desktop';",
    "description": "Detects whether the page is being viewed on a mobile device or a desktop.\n\n- Use a regular expression to test the `navigator.userAgent` property to figure out if the device is a mobile device or a desktop.",
    "example": "detectDeviceType(); // 'Mobile' or 'Desktop'",
    "id": "detectDeviceType",
    "tags": [
      "browser",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const detectLanguage = (defaultLang = 'en-US') => \n  navigator.language ||\n  (Array.isArray(navigator.languages) && navigator.languages[0]) ||\n  defaultLang;",
    "description": "Detects the preferred language of the current user.\n\n- Use `NavigationLanguage.language` or the first `NavigationLanguage.languages` if available, otherwise return `defaultLang`.\n- Omit the second argument, `defaultLang`, to use `'en-US'` as the default language code.",
    "example": "detectLanguage(); // 'nl-NL'",
    "id": "detectLanguage",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const difference = (a, b) => {\n  const s = new Set(b);\n  return a.filter(x => !s.has(x));\n};",
    "description": "Calculates the difference between two arrays, without filtering duplicate values.\n\n- Create a `Set` from `b` to get the unique values in `b`.\n- Use `Array.prototype.filter()` on `a` to only keep values not contained in `b`, using `Set.prototype.has()`.",
    "example": "difference([1, 2, 3, 3], [1, 2, 4]); // [3, 3]",
    "id": "difference",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const differenceBy = (a, b, fn) => {\n  const s = new Set(b.map(fn));\n  return a.map(fn).filter(el => !s.has(el));\n};",
    "description": "Returns the difference between two arrays, after applying the provided function to each array element of both.\n\n- Create a `Set` by applying `fn` to each element in `b`.\n- Use `Array.prototype.map()` to apply `fn` to each element in `a`.\n- Use `Array.prototype.filter()` in combination with `fn` on `a` to only keep values not contained in `b`, using `Set.prototype.has()`.",
    "example": "differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1]\ndifferenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [2]",
    "id": "differenceBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const differenceWith = (arr, val, comp = (a, b) => a === b) =>\n  arr.filter(a => val.findIndex(b => comp(a, b)) === -1);",
    "description": "Filters out all values from an array for which the comparator function does not return `true`.\n\n- Use `Array.prototype.filter()` and `Array.prototype.findIndex()` to find the appropriate values.\n- Omit the last argument, `comp`, to use a default strict equality comparator.",
    "example": "differenceWith(\n  [1, 1.2, 1.5, 3, 0],\n  [1.9, 3, 0],\n  (a, b) => Math.round(a) === Math.round(b)\n); // [1, 1.2]\ndifferenceWith([1, 1.2, 1.3], [1, 1.3, 1.5]); // [1.2]",
    "id": "differenceWith",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const dig = (obj, target) =>\n  target in obj\n    ? obj[target]\n    : Object.values(obj).reduce((acc, val) => {\n        if (acc !== undefined) return acc;\n        if (typeof val === 'object') return dig(val, target);\n      }, undefined);",
    "description": "Gets the target value in a nested JSON object, based on the given key.\n\n- Use the `in` operator to check if `target` exists in `obj`.\n- If found, return the value of `obj[target]`.\n- Otherwise use `Object.values(obj)` and `Array.prototype.reduce()` to recursively call `dig` on each nested object until the first matching key/value pair is found.",
    "example": "const data = {\n  level1: {\n    level2: {\n      level3: 'some data'\n    }\n  }\n};\ndig(data, 'level3'); // 'some data'\ndig(data, 'level4'); // undefined",
    "id": "dig",
    "tags": [
      "object",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const digitize = n => [...\\`\\${Math.abs(n)}\\`].map(i => parseInt(i));",
    "description": "Converts a number to an array of digits, removing its sign if necessary.\n\n- Use `Math.abs()` to strip the number's sign.\n- Convert the number to a string, using the spread operator (`...`) to build an array.\n- Use `Array.prototype.map()` and `parseInt()` to transform each value to an integer.",
    "example": "digitize(123); // [1, 2, 3]\ndigitize(-123); // [1, 2, 3]",
    "id": "digitize",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);",
    "description": "Calculates the distance between two points.\n\n- Use `Math.hypot()` to calculate the Euclidean distance between two points.",
    "example": "distance(1, 1, 2, 3); // ~2.2361",
    "id": "distance",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const divmod = (x, y) => [Math.floor(x / y), x % y];",
    "description": "Returns an array consisting of the quotient and remainder of the given numbers.\n\n- Use `Math.floor()` to get the quotient of the division `x / y`.\n- Use the modulo operator (`%`) to get the remainder of the division `x / y`.",
    "example": "divmod(8, 3); // [2, 2]\ndivmod(3, 8); // [0, 3]\ndivmod(5, 5); // [1, 0]",
    "id": "divmod",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const drop = (arr, n = 1) => arr.slice(n);",
    "description": "Creates a new array with `n` elements removed from the left.\n\n- Use `Array.prototype.slice()` to remove the specified number of elements from the left.\n- Omit the last argument, `n`, to use a default value of `1`.",
    "example": "drop([1, 2, 3]); // [2, 3]\ndrop([1, 2, 3], 2); // [3]\ndrop([1, 2, 3], 42); // []",
    "id": "drop",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const dropRight = (arr, n = 1) => arr.slice(0, -n);",
    "description": "Creates a new array with `n` elements removed from the right.\n\n- Use `Array.prototype.slice()` to remove the specified number of elements from the right.\n- Omit the last argument, `n`, to use a default value of `1`.",
    "example": "dropRight([1, 2, 3]); // [1, 2]\ndropRight([1, 2, 3], 2); // [1]\ndropRight([1, 2, 3], 42); // []",
    "id": "dropRight",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const dropRightWhile = (arr, func) => {\n  let rightIndex = arr.length;\n  while (rightIndex-- && !func(arr[rightIndex]));\n  return arr.slice(0, rightIndex + 1);\n};",
    "description": "Removes elements from the end of an array until the passed function returns `true`.\nReturns the remaining elements in the array.\n\n- Loop through the array, using `Array.prototype.slice()` to drop the last element of the array until the value returned from `func` is `true`.\n- Return the remaining elements.",
    "example": "dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2]",
    "id": "dropRightWhile",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const dropWhile = (arr, func) => {\n  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);\n  return arr;\n};",
    "description": "Removes elements in an array until the passed function returns `true`.\nReturns the remaining elements in the array.\n\n- Loop through the array, using `Array.prototype.slice()` to drop the first element of the array until the value returned from `func` is `true`.\n- Return the remaining elements.",
    "example": "dropWhile([1, 2, 3, 4], n => n >= 3); // [3, 4]",
    "id": "dropWhile",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const either = (f, g) => (...args) => f(...args) || g(...args);",
    "description": "Checks if at least one function returns `true` for a given set of arguments.\n\n- Use the logical or (`||`) operator on the result of calling the two functions with the supplied `args`.",
    "example": "const isEven = num => num % 2 === 0;\nconst isPositive = num => num > 0;\nconst isPositiveOrEven = either(isPositive, isEven);\nisPositiveOrEven(4); // true\nisPositiveOrEven(3); // true",
    "id": "either",
    "tags": [
      "function",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const elementContains = (parent, child) =>\n  parent !== child && parent.contains(child);",
    "description": "Checks if the `parent` element contains the `child` element.\n\n- Check that `parent` is not the same element as `child`.\n- Use `Node.contains()` to check if the `parent` element contains the `child` element.",
    "example": "elementContains(\n  document.querySelector('head'),\n  document.querySelector('title')\n);\n// true\nelementContains(document.querySelector('body'), document.querySelector('body'));\n// false",
    "id": "elementContains",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const elementIsFocused = el => (el === document.activeElement);",
    "description": "Checks if the given element is focused.\n\n- Use `Document.activeElement` to determine if the given element is focused.",
    "example": "elementIsFocused(el); // true if the element is focused",
    "id": "elementIsFocused",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const elementIsVisibleInViewport = (el, partiallyVisible = false) => {\n  const { top, left, bottom, right } = el.getBoundingClientRect();\n  const { innerHeight, innerWidth } = window;\n  return partiallyVisible\n    ? ((top > 0 && top < innerHeight) ||\n        (bottom > 0 && bottom < innerHeight)) &&\n        ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))\n    : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;\n};",
    "description": "Checks if the element specified is visible in the viewport.\n\n- Use `Element.getBoundingClientRect()` and the `Window.inner(Width|Height)` values to determine if a given element is visible in the viewport.\n- Omit the second argument to determine if the element is entirely visible, or specify `true` to determine if it is partially visible.",
    "example": "// e.g. 100x100 viewport and a 10x10px element at position {top: -1, left: 0, bottom: 9, right: 10}\nelementIsVisibleInViewport(el); // false - (not fully visible)\nelementIsVisibleInViewport(el, true); // true - (partially visible)",
    "id": "elementIsVisibleInViewport",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const equals = (a, b) => {\n  if (a === b) return true;\n\n  if (a instanceof Date && b instanceof Date)\n    return a.getTime() === b.getTime();\n\n  if (!a || !b || (typeof a !== 'object' && typeof b !== 'object'))\n    return a === b;\n\n  if (a.prototype !== b.prototype) return false;\n\n  const keys = Object.keys(a);\n  if (keys.length !== Object.keys(b).length) return false;\n\n  return keys.every(k => equals(a[k], b[k]));\n};",
    "description": "Performs a deep comparison between two values to determine if they are equivalent.\n\n- Check if the two values are identical.\n- Check if both values are `Date` objects with the same time, using `Date.prototype.getTime()`.\n- Check if both values are non-object values with an equivalent value (strict comparison).\n- Check if only one value is `null` or `undefined` or if their prototypes differ.\n- If none of the above conditions are met, use `Object.keys()` to check if both values have the same number of keys.\n- Use `Array.prototype.every()` to check if every key in `a` exists in `b` and if they are equivalent by calling `equals()` recursively.",
    "example": "equals(\n  { a: [2, { e: 3 }], b: [4], c: 'foo' },\n  { a: [2, { e: 3 }], b: [4], c: 'foo' }\n); // true\nequals([1, 2, 3], { 0: 1, 1: 2, 2: 3 }); // true",
    "id": "equals",
    "tags": [
      "object",
      "array",
      "type",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const escapeHTML = str =>\n  str.replace(\n    /[&<>'\"]/g,\n    tag =>\n      ({\n        '&': '&amp;',\n        '<': '&lt;',\n        '>': '&gt;',\n        \"'\": '&#39;',\n        '\"': '&quot;'\n      }[tag] || tag)\n  );",
    "description": "Escapes a string for use in HTML.\n\n- Use `String.prototype.replace()` with a regexp that matches the characters that need to be escaped.\n- Use the callback function to replace each character instance with its associated escaped character using a dictionary object.",
    "example": "escapeHTML('<a href=\"#\">Me & you</a>');\n// '&lt;a href=&quot;#&quot;&gt;Me &amp; you&lt;/a&gt;'",
    "id": "escapeHTML",
    "tags": [
      "string",
      "browser",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const escapeRegExp = str => str.replace(/[.*+?^\\${}()|[\\]\\\\]/g, '\\\\$&');",
    "description": "Escapes a string to use in a regular expression.\n\n- Use `String.prototype.replace()` to escape special characters.",
    "example": "escapeRegExp('(test)'); // \\\\(test\\\\)",
    "id": "escapeRegExp",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const euclideanDistance = (a, b) =>\n  Math.hypot(...Object.keys(a).map(k => b[k] - a[k]));",
    "description": "Calculates the distance between two points in any number of dimensions.\n\n- Use `Object.keys()` and `Array.prototype.map()` to map each coordinate to its difference between the two points.\n- Use `Math.hypot()` to calculate the Euclidean distance between the two points.",
    "example": "euclideanDistance([1, 1], [2, 3]); // ~2.2361\neuclideanDistance([1, 1, 1], [2, 3, 2]); // ~2.4495",
    "id": "euclideanDistance",
    "tags": [
      "math",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);",
    "description": "Returns every `nth` element in an array.\n\n- Use `Array.prototype.filter()` to create a new array that contains every `nth` element of a given array.",
    "example": "everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ]",
    "id": "everyNth",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const expandTabs = (str, count) => str.replace(/\\t/g, ' '.repeat(count));",
    "description": "Convert tabs to spaces, where each tab corresponds to `count` spaces.\n\n- Use `String.prototype.replace()` with a regular expression and `String.prototype.repeat()` to replace each tab character with `count` spaces.",
    "example": "expandTabs('\\t\\tlorem', 3); // '      lorem'",
    "id": "expandTabs",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const extendHex = shortHex =>\n  '#' +\n  shortHex\n    .slice(shortHex.startsWith('#') ? 1 : 0)\n    .split('')\n    .map(x => x + x)\n    .join('');",
    "description": "Extends a 3-digit color code to a 6-digit color code.\n\n- Use `Array.prototype.map()`, `String.prototype.split()` and `Array.prototype.join()` to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form.\n- `Array.prototype.slice()` is used to remove `#` from string start since it's added once.",
    "example": "extendHex('#03f'); // '#0033ff'\nextendHex('05a'); // '#0055aa'",
    "id": "extendHex",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const factorial = n =>\n  n < 0\n    ? (() => {\n        throw new TypeError('Negative numbers are not allowed!');\n      })()\n    : n <= 1\n    ? 1\n    : n * factorial(n - 1);",
    "description": "Calculates the factorial of a number.\n\n- Use recursion.\n- If `n` is less than or equal to `1`, return `1`.\n- Otherwise, return the product of `n` and the factorial of `n - 1`.\n- Throw a `TypeError` if `n` is a negative number.",
    "example": "factorial(6); // 720",
    "id": "factorial",
    "tags": [
      "math",
      "algorithm",
      "recursion",
      "beginner"
    ]
  },
  {
    "code": "const fahrenheitToCelsius = degrees => (degrees - 32) * 5 / 9;",
    "description": "Converts Fahrenheit to Celsius.\n\n- Follow the conversion formula `C = (F - 32) * 5/9`.",
    "example": "fahrenheitToCelsius(32); // 0",
    "id": "fahrenheitToCelsius",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const fibonacci = n =>\n  Array.from({ length: n }).reduce(\n    (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),\n    []\n  );",
    "description": "Generates an array, containing the Fibonacci sequence, up until the nth term.\n\n- Use `Array.from()` to create an empty array of the specific length, initializing the first two values (`0` and `1`).\n- Use `Array.prototype.reduce()` and `Array.prototype.concat()` to add values into the array, using the sum of the last two values, except for the first two.",
    "example": "fibonacci(6); // [0, 1, 1, 2, 3, 5]",
    "id": "fibonacci",
    "tags": [
      "math",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const filterNonUnique = arr =>\n  [...new Set(arr)].filter(i => arr.indexOf(i) === arr.lastIndexOf(i));",
    "description": "Creates an array with the non-unique values filtered out.\n\n- Use `new Set()` and the spread operator (`...`) to create an array of the unique values in `arr`.\n- Use `Array.prototype.filter()` to create an array containing only the unique values.",
    "example": "filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5]",
    "id": "filterNonUnique",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const filterNonUniqueBy = (arr, fn) =>\n  arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));",
    "description": "Creates an array with the non-unique values filtered out, based on a provided comparator function.\n\n- Use `Array.prototype.filter()` and `Array.prototype.every()` to create an array containing only the unique values, based on the comparator function, `fn`.\n- The comparator function takes four arguments: the values of the two elements being compared and their indexes.",
    "example": "filterNonUniqueBy(\n  [\n    { id: 0, value: 'a' },\n    { id: 1, value: 'b' },\n    { id: 2, value: 'c' },\n    { id: 1, value: 'd' },\n    { id: 0, value: 'e' }\n  ],\n  (a, b) => a.id === b.id\n); // [ { id: 2, value: 'c' } ]",
    "id": "filterNonUniqueBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const filterUnique = arr =>\n  [...new Set(arr)].filter(i => arr.indexOf(i) !== arr.lastIndexOf(i));",
    "description": "Creates an array with the unique values filtered out.\n\n- Use `new Set()` and the spread operator (`...`) to create an array of the unique values in `arr`.\n- Use `Array.prototype.filter()` to create an array containing only the non-unique values.",
    "example": "filterUnique([1, 2, 2, 3, 4, 4, 5]); // [2, 4]",
    "id": "filterUnique",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const filterUniqueBy = (arr, fn) =>\n  arr.filter((v, i) => arr.some((x, j) => (i !== j) === fn(v, x, i, j)));",
    "description": "Creates an array with the unique values filtered out, based on a provided comparator function.\n\n- Use `Array.prototype.filter()` and `Array.prototype.every()` to create an array containing only the non-unique values, based on the comparator function, `fn`.\n- The comparator function takes four arguments: the values of the two elements being compared and their indexes.",
    "example": "filterUniqueBy(\n  [\n    { id: 0, value: 'a' },\n    { id: 1, value: 'b' },\n    { id: 2, value: 'c' },\n    { id: 3, value: 'd' },\n    { id: 0, value: 'e' }\n  ],\n  (a, b) => a.id == b.id\n); // [ { id: 0, value: 'a' }, { id: 0, value: 'e' } ]",
    "id": "filterUniqueBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const findClosestAnchor = node => {\n  for (let n = node; n.parentNode; n = n.parentNode)\n    if (n.nodeName.toLowerCase() === 'a') return n;\n  return null;\n};",
    "description": "Finds the anchor node closest to the given `node`, if any.\n\n- Use a `for` loop and `Node.parentNode` to traverse the node tree upwards from the given `node`.\n- Use `Node.nodeName` and `String.prototype.toLowerCase()` to check if any given node is an anchor (`'a'`).\n- If no matching node is found, return `null`.",
    "example": "findClosestAnchor(document.querySelector('a > span')); // a",
    "id": "findClosestAnchor",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const findClosestMatchingNode = (node, selector) => {\n  for (let n = node; n.parentNode; n = n.parentNode)\n    if (n.matches && n.matches(selector)) return n;\n  return null;\n};",
    "description": "Finds the closest matching node starting at the given `node`.\n\n- Use a `for` loop and `Node.parentNode` to traverse the node tree upwards from the given `node`.\n- Use `Element.matches()` to check if any given element node matches the provided `selector`.\n- If no matching node is found, return `null`.",
    "example": "findClosestMatchingNode(document.querySelector('span'), 'body'); // body",
    "id": "findClosestMatchingNode",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const findFirstN = (arr, matcher, n = 1) => {\n  let res = [];\n  for (let i in arr) {\n    const el = arr[i];\n    const match = matcher(el, i, arr);\n    if (match) res.push(el);\n    if (res.length === n) return res;\n  }\n  return res;\n};",
    "description": "Finds the first `n` elements for which the provided function returns a truthy value.\n\n- Use a `for..in` loop to execute the provided `matcher` for each element of `arr`.\n- Use `Array.prototype.push()` to append elements to the results array and return them if its `length` is equal to `n`.",
    "example": "findFirstN([1, 2, 4, 6], n => n % 2 === 0, 2); // [2, 4]\nfindFirstN([1, 2, 4, 6], n => n % 2 === 0, 5); // [2, 4, 6]",
    "id": "findFirstN",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const findKey = (obj, fn) => \n  Object.keys(obj).find(key => fn(obj[key], key, obj));",
    "description": "Finds the first key that satisfies the provided testing function.\nOtherwise `undefined` is returned.\n\n- Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.find()` to test each key-value pair using `fn`.\n- The callback receives three arguments - the value, the key and the object.",
    "example": "findKey(\n  {\n    barney: { age: 36, active: true },\n    fred: { age: 40, active: false },\n    pebbles: { age: 1, active: true }\n  },\n  x => x['active']\n); // 'barney'",
    "id": "findKey",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const findKeys = (obj, val) => \n  Object.keys(obj).filter(key => obj[key] === val);",
    "description": "Finds all the keys in the provided object that match the given value.\n\n- Use `Object.keys(obj)` to get all the properties of the object.\n- Use `Array.prototype.filter()` to test each key-value pair and return all keys that are equal to the given value.",
    "example": "const ages = {\n  Leo: 20,\n  Zoey: 21,\n  Jane: 20,\n};\nfindKeys(ages, 20); // [ 'Leo', 'Jane' ]",
    "id": "findKeys",
    "tags": [
      "object",
      "beginner"
    ]
  },
  {
    "code": "const findLast = (arr, fn) => arr.filter(fn).pop();",
    "description": "Finds the last element for which the provided function returns a truthy value.\n\n- Use `Array.prototype.filter()` to remove elements for which `fn` returns falsy values.\n- Use `Array.prototype.pop()` to get the last element in the filtered array.",
    "example": "findLast([1, 2, 3, 4], n => n % 2 === 1); // 3",
    "id": "findLast",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const findLastIndex = (arr, fn) =>\n  (arr\n    .map((val, i) => [i, val])\n    .filter(([i, val]) => fn(val, i, arr))\n    .pop() || [-1])[0];",
    "description": "Finds the index of the last element for which the provided function returns a truthy value.\n\n- Use `Array.prototype.map()` to map each element to an array with its index and value.\n- Use `Array.prototype.filter()` to remove elements for which `fn` returns falsy values\n- Use `Array.prototype.pop()` to get the last element in the filtered array.\n- Return `-1` if there are no matching elements.",
    "example": "findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3)\nfindLastIndex([1, 2, 3, 4], n => n === 5); // -1 (default value when not found)",
    "id": "findLastIndex",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const findLastKey = (obj, fn) =>\n  Object.keys(obj)\n    .reverse()\n    .find(key => fn(obj[key], key, obj));",
    "description": "Finds the last key that satisfies the provided testing function.\nOtherwise `undefined` is returned.\n\n- Use `Object.keys(obj)` to get all the properties of the object.\n- Use `Array.prototype.reverse()` to reverse the order and `Array.prototype.find()` to test the provided function for each key-value pair.\n- The callback receives three arguments - the value, the key and the object.",
    "example": "findLastKey(\n  {\n    barney: { age: 36, active: true },\n    fred: { age: 40, active: false },\n    pebbles: { age: 1, active: true }\n  },\n  x => x['active']\n); // 'pebbles'",
    "id": "findLastKey",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const findLastN = (arr, matcher, n = 1) => {\n  let res = [];\n  for (let i = arr.length - 1; i >= 0; i--) {\n    const el = arr[i];\n    const match = matcher(el, i, arr);\n    if (match) res.unshift(el);\n    if (res.length === n) return res;\n  }\n  return res;\n};",
    "description": "Finds the last `n` elements for which the provided function returns a truthy value.\n\n- Use a `for` loop to execute the provided `matcher` for each element of `arr`.\n- Use `Array.prototype.unshift()` to prepend elements to the results array and return them if its `length` is equal to `n`.",
    "example": "findLastN([1, 2, 4, 6], n => n % 2 === 0, 2); // [4, 6]\nfindLastN([1, 2, 4, 6], n => n % 2 === 0, 5); // [2, 4, 6]",
    "id": "findLastN",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const flatten = (arr, depth = 1) =>\n  arr.reduce(\n    (a, v) =>\n      a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v),\n    []\n  );",
    "description": "Flattens an array up to the specified depth.\n\n- Use recursion, decrementing `depth` by `1` for each level of depth.\n- Use `Array.prototype.reduce()` and `Array.prototype.concat()` to merge elements or arrays.\n- Base case, for `depth` equal to `1` stops recursion.\n- Omit the second argument, `depth`, to flatten only to a depth of `1` (single flatten).",
    "example": "flatten([1, [2], 3, 4]); // [1, 2, 3, 4]\nflatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]",
    "id": "flatten",
    "tags": [
      "array",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const flattenObject = (obj, prefix = '') =>\n  Object.keys(obj).reduce((acc, k) => {\n    const pre = prefix.length ? \\`\\${prefix}.\\` : '';\n    if (\n      typeof obj[k] === 'object' &&\n      obj[k] !== null &&\n      Object.keys(obj[k]).length > 0\n    )\n      Object.assign(acc, flattenObject(obj[k], pre + k));\n    else acc[pre + k] = obj[k];\n    return acc;\n  }, {});",
    "description": "Flattens an object with the paths for keys.\n\n- Use recursion.\n- Use `Object.keys(obj)` combined with `Array.prototype.reduce()` to convert every leaf node to a flattened path node.\n- If the value of a key is an object, the function calls itself with the appropriate `prefix` to create the path using `Object.assign()`.\n- Otherwise, it adds the appropriate prefixed key-value pair to the accumulator object.\n- You should always omit the second argument, `prefix`, unless you want every key to have a prefix.",
    "example": "flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 }",
    "id": "flattenObject",
    "tags": [
      "object",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const flip = fn => (first, ...rest) => fn(...rest, first);",
    "description": "Takes a function as an argument, then makes the first argument the last.\n\n- Use argument destructuring and a closure with variadic arguments.\n- Splice the first argument, using the spread operator (`...`), to make it the last before applying the rest.",
    "example": "let a = { name: 'John Smith' };\nlet b = {};\nconst mergeFrom = flip(Object.assign);\nlet mergePerson = mergeFrom.bind(null, a);\nmergePerson(b); // == b\nb = {};\nObject.assign(b, a); // == b",
    "id": "flip",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const forEachRight = (arr, callback) =>\n  arr\n    .slice()\n    .reverse()\n    .forEach(callback);",
    "description": "Executes a provided function once for each array element, starting from the array's last element.\n\n- Use `Array.prototype.slice()` to clone the given array and `Array.prototype.reverse()` to reverse it.\n- Use `Array.prototype.forEach()` to iterate over the reversed array.",
    "example": "forEachRight([1, 2, 3, 4], val => console.log(val)); // '4', '3', '2', '1'",
    "id": "forEachRight",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const forOwn = (obj, fn) =>\n  Object.keys(obj).forEach(key => fn(obj[key], key, obj));",
    "description": "Iterates over all own properties of an object, running a callback for each one.\n\n- Use `Object.keys(obj)` to get all the properties of the object.\n- Use `Array.prototype.forEach()` to run the provided function for each key-value pair.\n- The callback receives three arguments - the value, the key and the object.",
    "example": "forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1",
    "id": "forOwn",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const forOwnRight = (obj, fn) =>\n  Object.keys(obj)\n    .reverse()\n    .forEach(key => fn(obj[key], key, obj));",
    "description": "Iterates over all own properties of an object in reverse, running a callback for each one.\n\n- Use `Object.keys(obj)` to get all the properties of the object, `Array.prototype.reverse()` to reverse their order.\n- Use `Array.prototype.forEach()` to run the provided function for each key-value pair.\n- The callback receives three arguments - the value, the key and the object.",
    "example": "forOwnRight({ foo: 'bar', a: 1 }, v => console.log(v)); // 1, 'bar'",
    "id": "forOwnRight",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const formToObject = form =>\n  Array.from(new FormData(form)).reduce(\n    (acc, [key, value]) => ({\n      ...acc,\n      [key]: value\n    }),\n    {}\n  );",
    "description": "Encodes a set of form elements as an `object`.\n\n- Use the `FormData` constructor to convert the HTML `form` to `FormData` and `Array.from()` to convert to an array.\n- Collect the object from the array using `Array.prototype.reduce()`.",
    "example": "formToObject(document.querySelector('#form'));\n// { email: 'test@email.com', name: 'Test Name' }",
    "id": "formToObject",
    "tags": [
      "browser",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const formatDuration = ms => {\n  if (ms < 0) ms = -ms;\n  const time = {\n    day: Math.floor(ms / 86400000),\n    hour: Math.floor(ms / 3600000) % 24,\n    minute: Math.floor(ms / 60000) % 60,\n    second: Math.floor(ms / 1000) % 60,\n    millisecond: Math.floor(ms) % 1000\n  };\n  return Object.entries(time)\n    .filter(val => val[1] !== 0)\n    .map(([key, val]) => \\`\\${val} \\${key}\\${val !== 1 ? 's' : ''}\\`)\n    .join(', ');\n};",
    "description": "Returns the human-readable format of the given number of milliseconds.\n\n- Divide `ms` with the appropriate values to obtain the appropriate values for `day`, `hour`, `minute`, `second` and `millisecond`.\n- Use `Object.entries()` with `Array.prototype.filter()` to keep only non-zero values.\n- Use `Array.prototype.map()` to create the string for each value, pluralizing appropriately.\n- Use `String.prototype.join(', ')` to combine the values into a string.",
    "example": "formatDuration(1001); // '1 second, 1 millisecond'\nformatDuration(34325055574);\n// '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds'",
    "id": "formatDuration",
    "tags": [
      "date",
      "math",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const formatNumber = num => num.toLocaleString();",
    "description": "Formats a number using the local number format order.\n\n- Use `Number.prototype.toLocaleString()` to convert a number to using the local number format separators.",
    "example": "formatNumber(123456); // '123,456' in `en-US`\nformatNumber(15675436903); // '15.675.436.903' in `de-DE`",
    "id": "formatNumber",
    "tags": [
      "string",
      "math",
      "beginner"
    ]
  },
  {
    "code": "const formatSeconds = s => {\n  const [hour, minute, second, sign] =\n    s > 0\n      ? [s / 3600, (s / 60) % 60, s % 60, '']\n      : [-s / 3600, (-s / 60) % 60, -s % 60, '-'];\n\n  return (\n    sign +\n    [hour, minute, second]\n      .map(v => \\`\\${Math.floor(v)}\\`.padStart(2, '0'))\n      .join(':')\n  );\n};",
    "description": "Returns the ISO format of the given number of seconds.\n\n- Divide `s` with the appropriate values to obtain the appropriate values for `hour`, `minute` and `second`.\n- Store the `sign` in a variable to prepend it to the result.\n- Use `Array.prototype.map()` in combination with `Math.floor()` and `String.prototype.padStart()` to stringify and format each segment.\n- Use `String.prototype.join(':')` to combine the values into a string.",
    "example": "formatSeconds(200); // '00:03:20'\nformatSeconds(-200); // '-00:03:20'\nformatSeconds(99999); // '27:46:39'",
    "id": "formatSeconds",
    "tags": [
      "date",
      "math",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const frequencies = arr =>\n  arr.reduce((a, v) => {\n    a[v] = a[v] ? a[v] + 1 : 1;\n    return a;\n  }, {});",
    "description": "Creates an object with the unique values of an array as keys and their frequencies as the values.\n\n- Use `Array.prototype.reduce()` to map unique values to an object's keys, adding to existing keys every time the same value is encountered.",
    "example": "frequencies(['a', 'b', 'a', 'c', 'a', 'a', 'b']); // { a: 4, b: 2, c: 1 }\nfrequencies([...'ball']); // { b: 1, a: 1, l: 2 }",
    "id": "frequencies",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const fromCamelCase = (str, separator = '_') =>\n  str\n    .replace(/([a-z\\d])([A-Z])/g, '$1' + separator + '$2')\n    .replace(/([A-Z]+)([A-Z][a-z\\d]+)/g, '$1' + separator + '$2')\n    .toLowerCase();",
    "description": "Converts a string from camelcase.\n\n- Use `String.prototype.replace()` to break the string into words and add a `separator` between them.\n- Omit the second argument to use a default `separator` of `_`.",
    "example": "fromCamelCase('someDatabaseFieldName', ' '); // 'some database field name'\nfromCamelCase('someLabelThatNeedsToBeDecamelized', '-'); \n// 'some-label-that-needs-to-be-decamelized'\nfromCamelCase('someJavascriptProperty', '_'); // 'some_javascript_property'\nfromCamelCase('JSONToCSV', '.'); // 'json.to.csv'",
    "id": "fromCamelCase",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const fromTimestamp = timestamp => new Date(timestamp * 1000);",
    "description": "Creates a `Date` object from a Unix timestamp.\n\n- Convert the timestamp to milliseconds by multiplying with `1000`.\n- Use `new Date()` to create a new `Date` object.",
    "example": "fromTimestamp(1602162242); // 2020-10-08T13:04:02.000Z",
    "id": "fromTimestamp",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const frozenSet = iterable => {\n  const s = new Set(iterable);\n  s.add = undefined;\n  s.delete = undefined;\n  s.clear = undefined;\n  return s;\n};",
    "description": "Creates a frozen `Set` object.\n\n- Use the `new Set()` constructor to create a new `Set` object from `iterable`.\n- Set the `add`, `delete` and `clear` methods of the newly created object to `undefined`, so that they cannot be used, practically freezing the object.",
    "example": "frozenSet([1, 2, 3, 1, 2]); \n// Set { 1, 2, 3, add: undefined, delete: undefined, clear: undefined }",
    "id": "frozenSet",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const fullscreen = (mode = true, el = 'body') =>\n  mode\n    ? document.querySelector(el).requestFullscreen()\n    : document.exitFullscreen();",
    "description": "Opens or closes an element in fullscreen mode.\n\n- Use `Document.querySelector()` and `Element.requestFullscreen()` to open the given element in fullscreen.\n- Use `Document.exitFullscreen()` to exit fullscreen mode.\n- Omit the second argument, `el`, to use `body` as the default element.\n- Omit the first element, `mode`, to open the element in fullscreen mode by default.",
    "example": "fullscreen(); // Opens `body` in fullscreen mode\nfullscreen(false); // Exits fullscreen mode",
    "id": "fullscreen",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const functionName = fn => (console.debug(fn.name), fn);",
    "description": "Logs the name of a function.\n\n- Use `console.debug()` and the `name` property of the passed function to log the function's name to the `debug` channel of the console.\n- Return the given function `fn`.",
    "example": "let m = functionName(Math.max)(5, 6);\n// max (logged in debug channel of console)\n// m = 6",
    "id": "functionName",
    "tags": [
      "function",
      "beginner"
    ]
  },
  {
    "code": "const functions = (obj, inherited = false) =>\n  (inherited\n    ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))]\n    : Object.keys(obj)\n  ).filter(key => typeof obj[key] === 'function');",
    "description": "Gets an array of function property names from own (and optionally inherited) enumerable properties of an object.\n\n- Use `Object.keys(obj)` to iterate over the object's own properties.\n- If `inherited` is `true`, use `Object.getPrototypeOf(obj)` to also get the object's inherited properties.\n- Use `Array.prototype.filter()` to keep only those properties that are functions.\n- Omit the second argument, `inherited`, to not include inherited properties by default.",
    "example": "function Foo() {\n  this.a = () => 1;\n  this.b = () => 2;\n}\nFoo.prototype.c = () => 3;\nfunctions(new Foo()); // ['a', 'b']\nfunctions(new Foo(), true); // ['a', 'b', 'c']",
    "id": "functions",
    "tags": [
      "object",
      "function",
      "advanced"
    ]
  },
  {
    "code": "const gcd = (...arr) => {\n  const _gcd = (x, y) => (!y ? x : gcd(y, x % y));\n  return [...arr].reduce((a, b) => _gcd(a, b));\n};",
    "description": "Calculates the greatest common divisor between two or more numbers/arrays.\n\n- The inner `_gcd` function uses recursion.\n- Base case is when `y` equals `0`. In this case, return `x`.\n- Otherwise, return the GCD of `y` and the remainder of the division `x/y`.",
    "example": "gcd(8, 36); // 4\ngcd(...[12, 8, 32]); // 4",
    "id": "gcd",
    "tags": [
      "math",
      "algorithm",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const generateItems = (n, fn) => Array.from({ length: n }, (_, i) => fn(i));",
    "description": "Generates an array with the given amount of items, using the given function.\n\n- Use  `Array.from()`  to create an empty array of the specific length, calling `fn` with the index of each newly created element.\n- The callback takes one argument - the index of each element.",
    "example": "generateItems(10, Math.random);\n// [0.21, 0.08, 0.40, 0.96, 0.96, 0.24, 0.19, 0.96, 0.42, 0.70]",
    "id": "generateItems",
    "tags": [
      "array",
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const generatorToArray = gen => [...gen];",
    "description": "Converts the output of a generator function to an array.\n\n- Use the spread operator (`...`) to convert the output of the generator function to an array.",
    "example": "const s = new Set([1, 2, 1, 3, 1, 4]);\ngeneratorToArray(s.entries()); // [[ 1, 1 ], [ 2, 2 ], [ 3, 3 ], [ 4, 4 ]]",
    "id": "generatorToArray",
    "tags": [
      "function",
      "array",
      "generator",
      "beginner"
    ]
  },
  {
    "code": "const geometricProgression = (end, start = 1, step = 2) =>\n  Array.from({\n    length: Math.floor(Math.log(end / start) / Math.log(step)) + 1,\n  }).map((_, i) => start * step ** i);",
    "description": "Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive and the ratio between two terms is `step`.\nReturns an error if `step` equals `1`.\n\n- Use `Array.from()`, `Math.log()` and `Math.floor()` to create an array of the desired length, `Array.prototype.map()` to fill with the desired values in a range.\n- Omit the second argument, `start`, to use a default value of `1`.\n- Omit the third argument, `step`, to use a default value of `2`.",
    "example": "geometricProgression(256); // [1, 2, 4, 8, 16, 32, 64, 128, 256]\ngeometricProgression(256, 3); // [3, 6, 12, 24, 48, 96, 192]\ngeometricProgression(256, 1, 4); // [1, 4, 16, 64, 256]",
    "id": "geometricProgression",
    "tags": [
      "math",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const get = (from, ...selectors) =>\n  [...selectors].map(s =>\n    s\n      .replace(/\\[([^\\[\\]]*)\\]/g, '.$1.')\n      .split('.')\n      .filter(t => t !== '')\n      .reduce((prev, cur) => prev && prev[cur], from)\n  );",
    "description": "Retrieves a set of properties indicated by the given selectors from an object.\n\n- Use `Array.prototype.map()` for each selector, `String.prototype.replace()` to replace square brackets with dots.\n- Use `String.prototype.split('.')` to split each selector.\n- Use `Array.prototype.filter()` to remove empty values and `Array.prototype.reduce()` to get the value indicated by each selector.",
    "example": "const obj = {\n  selector: { to: { val: 'val to select' } },\n  target: [1, 2, { a: 'test' }],\n};\nget(obj, 'selector.to.val', 'target[0]', 'target[2].a');\n// ['val to select', 1, 'test']",
    "id": "get",
    "tags": [
      "object",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const getAncestors = el => {\n  let ancestors = [];\n  while (el) {\n    ancestors.unshift(el);\n    el = el.parentNode;\n  }\n  return ancestors;\n};",
    "description": "Returns all the ancestors of an element from the document root to the given element.\n\n- Use `Node.parentNode` and a `while` loop to move up the ancestor tree of the element.\n- Use `Array.prototype.unshift()` to add each new ancestor to the start of the array.",
    "example": "getAncestors(document.querySelector('nav')); \n// [document, html, body, header, nav]",
    "id": "getAncestors",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const getBaseURL = url => url.replace(/[?#].*$/, '');",
    "description": "Gets the current URL without any parameters or fragment identifiers.\n\n- Use `String.prototype.replace()` with an appropriate regular expression to remove everything after either `'?'` or `'#'`, if found.",
    "example": "getBaseURL('http://url.com/page?name=Adam&surname=Smith');\n// 'http://url.com/page'",
    "id": "getBaseURL",
    "tags": [
      "string",
      "browser",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);",
    "description": "Returns a string of the form `HH:MM:SS` from a `Date` object.\n\n- Use `Date.prototype.toTimeString()` and `String.prototype.slice()` to get the `HH:MM:SS` part of a given `Date` object.",
    "example": "getColonTimeFromDate(new Date()); // '08:38:00'",
    "id": "getColonTimeFromDate",
    "tags": [
      "date",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>\n  (dateFinal - dateInitial) / (1000 * 3600 * 24);",
    "description": "Calculates the difference (in days) between two dates.\n\n- Subtract the two `Date` objects and divide by the number of milliseconds in a day to get the difference (in days) between them.",
    "example": "getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9",
    "id": "getDaysDiffBetweenDates",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const getElementsBiggerThanViewport = () => {\n  const docWidth = document.documentElement.offsetWidth;\n  return [...document.querySelectorAll('*')].filter(\n    el => el.offsetWidth > docWidth\n  );\n};",
    "description": "Returns an array of HTML elements whose width is larger than that of the viewport's.\n\n- Use `HTMLElement.offsetWidth` to get the width of the `document`.\n- Use `Array.prototype.filter()` on the result of `Document.querySelectorAll()` to check the width of all elements in the document.",
    "example": "getElementsBiggerThanViewport(); // <div id=\"ultra-wide-item\" />",
    "id": "getElementsBiggerThanViewport",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const getHoursDiffBetweenDates = (dateInitial, dateFinal) =>\n  (dateFinal - dateInitial) / (1000 * 3600);",
    "description": "Calculates the difference (in hours) between two dates.\n\n- Subtract the two `Date` objects and divide by the number of milliseconds in an hour to get the difference (in hours) between them.",
    "example": "getHoursDiffBetweenDates(\n  new Date('2021-04-24 10:25:00'),\n  new Date('2021-04-25 10:25:00')\n); // 24",
    "id": "getHoursDiffBetweenDates",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const getImages = (el, includeDuplicates = false) => {\n  const images = [...el.getElementsByTagName('img')].map(img =>\n    img.getAttribute('src')\n  );\n  return includeDuplicates ? images : [...new Set(images)];\n};",
    "description": "Fetches all images from within an element and puts them into an array.\n\n- Use `Element.getElementsByTagName()` to get all `<img>` elements inside the provided element.\n- Use `Array.prototype.map()` to map every `src` attribute of each `<img>` element.\n- If `includeDuplicates` is `false`, create a new `Set` to eliminate duplicates and return it after spreading into an array.\n- Omit the second argument, `includeDuplicates`, to discard duplicates by default.",
    "example": "getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...']\ngetImages(document, false); // ['image1.jpg', 'image2.png', '...']",
    "id": "getImages",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const getMeridiemSuffixOfInteger = num =>\n  num === 0 || num === 24\n    ? 12 + 'am'\n    : num === 12\n    ? 12 + 'pm'\n    : num < 12\n    ? (num % 12) + 'am'\n    : (num % 12) + 'pm';",
    "description": "Converts an integer to a suffixed string, adding `am` or `pm` based on its value.\n\n- Use the modulo operator (`%`) and conditional checks to transform an integer to a stringified 12-hour format with meridiem suffix.",
    "example": "getMeridiemSuffixOfInteger(0); // '12am'\ngetMeridiemSuffixOfInteger(11); // '11am'\ngetMeridiemSuffixOfInteger(13); // '1pm'\ngetMeridiemSuffixOfInteger(25); // '1pm'",
    "id": "getMeridiemSuffixOfInteger",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const getMinutesDiffBetweenDates = (dateInitial, dateFinal) =>\n  (dateFinal - dateInitial) / (1000 * 60);",
    "description": "Calculates the difference (in minutes) between two dates.\n\n- Subtract the two `Date` objects and divide by the number of milliseconds in a minute to get the difference (in minutes) between them.",
    "example": "getMinutesDiffBetweenDates(\n  new Date('2021-04-24 01:00:15'),\n  new Date('2021-04-24 02:00:15')\n); // 60",
    "id": "getMinutesDiffBetweenDates",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const getMonthsDiffBetweenDates = (dateInitial, dateFinal) =>\n  Math.max(\n    (dateFinal.getFullYear() - dateInitial.getFullYear()) * 12 +\n      dateFinal.getMonth() -\n      dateInitial.getMonth(),\n    0\n  );",
    "description": "Calculates the difference (in months) between two dates.\n\n- Use `Date.prototype.getFullYear()` and `Date.prototype.getMonth()` to calculate the difference (in months) between two `Date` objects.",
    "example": "getMonthsDiffBetweenDates(new Date('2017-12-13'), new Date('2018-04-29')); // 4",
    "id": "getMonthsDiffBetweenDates",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const getParentsUntil = (el, selector) => {\n  let parents = [],\n    _el = el.parentNode;\n  while (_el && typeof _el.matches === 'function') {\n    parents.unshift(_el);\n    if (_el.matches(selector)) return parents;\n    else _el = _el.parentNode;\n  }\n  return [];\n};",
    "description": "Finds all the ancestors of an element up until the element matched by the specified selector.\n\n- Use `Node.parentNode` and a `while` loop to move up the ancestor tree of the element.\n- Use `Array.prototype.unshift()` to add each new ancestor to the start of the array.\n- Use `Element.matches()` to check if the current element matches the specified `selector`.",
    "example": "getParentsUntil(document.querySelector('#home-link'), 'header');\n// [header, nav, ul, li]",
    "id": "getParentsUntil",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const getProtocol = () => window.location.protocol;",
    "description": "Gets the protocol being used on the current page.\n\n- Use `Window.location.protocol` to get the protocol (`http:` or `https:`) of the current page.",
    "example": "getProtocol(); // 'https:'",
    "id": "getProtocol",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const getScrollPosition = (el = window) => ({\n  x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,\n  y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop\n});",
    "description": "Returns the scroll position of the current page.\n\n- Use `Window.pageXOffset` and `Window.pageYOffset` if they are defined, otherwise `Element.scrollLeft` and `Element.scrollTop`.\n- Omit the single argument, `el`, to use a default value of `window`.",
    "example": "getScrollPosition(); // {x: 0, y: 200}",
    "id": "getScrollPosition",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const getSecondsDiffBetweenDates = (dateInitial, dateFinal) =>\n  (dateFinal - dateInitial) / 1000;",
    "description": "Calculates the difference (in seconds) between two dates.\n\n- Subtract the two `Date` objects and divide by the number of milliseconds in a second to get the difference (in seconds) between them.",
    "example": "getSecondsDiffBetweenDates(\n  new Date('2020-12-24 00:00:15'),\n  new Date('2020-12-24 00:00:17')\n); // 2",
    "id": "getSecondsDiffBetweenDates",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const getSelectedText = () => window.getSelection().toString();",
    "description": "Gets the currently selected text.\n\n- Use `Window.getSelection()` and `Selection.toString()` to get the currently selected text.",
    "example": "getSelectedText(); // 'Lorem ipsum'",
    "id": "getSelectedText",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const getSiblings = el =>\n  [...el.parentNode.childNodes].filter(node => node !== el);",
    "description": "Returns an array containing all the siblings of the given element.\n\n- Use `Node.parentNode` and `Node.childNodes` to get a `NodeList` of all the elements contained in the element's parent.\n- Use the spread operator (`...`) and `Array.prototype.filter()` to convert to an array and remove the given element from it.",
    "example": "getSiblings(document.querySelector('head')); // ['body']",
    "id": "getSiblings",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];",
    "description": "Retrieves the value of a CSS rule for the specified element.\n\n- Use `Window.getComputedStyle()` to get the value of the CSS rule for the specified element.",
    "example": "getStyle(document.querySelector('p'), 'font-size'); // '16px'",
    "id": "getStyle",
    "tags": [
      "browser",
      "css",
      "beginner"
    ]
  },
  {
    "code": "const getTimestamp = (date = new Date()) => Math.floor(date.getTime() / 1000);",
    "description": "Gets the Unix timestamp from a `Date` object.\n\n- Use `Date.prototype.getTime()` to get the timestamp in milliseconds and divide by `1000` to get the timestamp in seconds.\n- Use `Math.floor()` to appropriately round the resulting timestamp to an integer.\n- Omit the argument, `date`, to use the current date.",
    "example": "getTimestamp(); // 1602162242",
    "id": "getTimestamp",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const getType = v =>\n  (v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name);",
    "description": "Returns the native type of a value.\n\n- Return `'undefined'` or `'null'` if the value is `undefined` or `null`.\n- Otherwise, use `Object.prototype.constructor.name` to get the name of the constructor.",
    "example": "getType(new Set([1, 2, 3])); // 'Set'",
    "id": "getType",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const getURLParameters = url =>\n  (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(\n    (a, v) => (\n      (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a\n    ),\n    {}\n  );",
    "description": "Creates an object containing the parameters of the current URL.\n\n- Use `String.prototype.match()` with an appropriate regular expression to get all key-value pairs.\n- Use `Array.prototype.reduce()` to map and combine them into a single object.\n- Pass `location.search` as the argument to apply to the current `url`.",
    "example": "getURLParameters('google.com'); // {}\ngetURLParameters('http://url.com/page?name=Adam&surname=Smith');\n// {name: 'Adam', surname: 'Smith'}",
    "id": "getURLParameters",
    "tags": [
      "browser",
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const getVerticalOffset = el => {\n  let offset = el.offsetTop,\n    _el = el;\n  while (_el.offsetParent) {\n    _el = _el.offsetParent;\n    offset += _el.offsetTop;\n  }\n  return offset;\n};",
    "description": "Finds the distance from a given element to the top of the document.\n\n- Use a `while` loop and `HTMLElement.offsetParent` to move up the offset parents of the given element.\n- Add `HTMLElement.offsetTop` for each element and return the result.",
    "example": "getVerticalOffset('.my-element'); // 120",
    "id": "getVerticalOffset",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const groupBy = (arr, fn) =>\n  arr\n    .map(typeof fn === 'function' ? fn : val => val[fn])\n    .reduce((acc, val, i) => {\n      acc[val] = (acc[val] || []).concat(arr[i]);\n      return acc;\n    }, {});",
    "description": "Groups the elements of an array based on the given function.\n\n- Use `Array.prototype.map()` to map the values of the array to a function or property name.\n- Use `Array.prototype.reduce()` to create an object, where the keys are produced from the mapped results.",
    "example": "groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]}\ngroupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}",
    "id": "groupBy",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const hammingDistance = (num1, num2) =>\n  ((num1 ^ num2).toString(2).match(/1/g) || '').length;",
    "description": "Calculates the Hamming distance between two values.\n\n- Use the XOR operator (`^`) to find the bit difference between the two numbers.\n- Convert to a binary string using `Number.prototype.toString(2)`.\n- Count and return the number of `1`s in the string, using `String.prototype.match(/1/g)`.",
    "example": "hammingDistance(2, 3); // 1",
    "id": "hammingDistance",
    "tags": [
      "math",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const hasClass = (el, className) => el.classList.contains(className);",
    "description": "Checks if the given element has the specified class.\n\n- Use `Element.classList` and `DOMTokenList.contains()` to check if the element has the specified class.",
    "example": "hasClass(document.querySelector('p.special'), 'special'); // true",
    "id": "hasClass",
    "tags": [
      "browser",
      "css",
      "beginner"
    ]
  },
  {
    "code": "const hasDuplicates = arr => new Set(arr).size !== arr.length;",
    "description": "Checks if there are duplicate values in a flat array.\n\n- Use `Set()` to get the unique values in the array.\n- Use `Set.prototype.size` and `Array.prototype.length` to check if the count of the unique values is the same as elements in the original array.",
    "example": "hasDuplicates([0, 1, 1, 2]); // true\nhasDuplicates([0, 1, 2, 3]); // false",
    "id": "hasDuplicates",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const hasFlags = (...flags) =>\n  flags.every(flag =>\n    process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)\n  );",
    "description": "Checks if the current process's arguments contain the specified flags.\n\n- Use `Array.prototype.every()` and `Array.prototype.includes()` to check if `process.argv` contains all the specified flags.\n- Use a regular expression to test if the specified flags are prefixed with `-` or `--` and prefix them accordingly.",
    "example": "// node myScript.js -s --test --cool=true\nhasFlags('-s'); // true\nhasFlags('--test', 'cool=true', '-s'); // true\nhasFlags('special'); // false",
    "id": "hasFlags",
    "tags": [
      "node",
      "intermediate"
    ]
  },
  {
    "code": "const hasKey = (obj, keys) => {\n  return (\n    keys.length > 0 &&\n    keys.every(key => {\n      if (typeof obj !== 'object' || !obj.hasOwnProperty(key)) return false;\n      obj = obj[key];\n      return true;\n    })\n  );\n};",
    "description": "Checks if the target value exists in a JSON object.\n\n- Check if `keys` is non-empty and use `Array.prototype.every()` to sequentially check its keys to internal depth of the object, `obj`.\n- Use `Object.prototype.hasOwnProperty()` to check if `obj` does not have the current key or is not an object, stop propagation and return `false`.\n- Otherwise assign the key's value to `obj` to use on the next iteration.\n- Return `false` beforehand if given key list is empty.",
    "example": "let obj = {\n  a: 1,\n  b: { c: 4 },\n  'b.d': 5\n};\nhasKey(obj, ['a']); // true\nhasKey(obj, ['b']); // true\nhasKey(obj, ['b', 'c']); // true\nhasKey(obj, ['b.d']); // true\nhasKey(obj, ['d']); // false\nhasKey(obj, ['c']); // false\nhasKey(obj, ['b', 'f']); // false",
    "id": "hasKey",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const hasMany = (arr, fn) => arr.filter(fn).length > 1;",
    "description": "Checks if an array has more than one value matching the given function.\n\n- Use `Array.prototype.filter()` in combination with `fn` to find all matching array elements.\n- Use `Array.prototype.length` to check if more than one element match `fn`.",
    "example": "hasMany([1, 3], x => x % 2); // true\nhasMany([1, 2], x => x % 2); // false",
    "id": "hasMany",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const hasOne = (arr, fn) => arr.filter(fn).length === 1;",
    "description": "Checks if an array has only one value matching the given function.\n\n- Use `Array.prototype.filter()` in combination with `fn` to find all matching array elements.\n- Use `Array.prototype.length` to check if only one element matches `fn`.",
    "example": "hasOne([1, 2], x => x % 2); // true\nhasOne([1, 3], x => x % 2); // false",
    "id": "hasOne",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const hashBrowser = val =>\n  crypto.subtle\n    .digest('SHA-256', new TextEncoder('utf-8').encode(val))\n    .then(h => {\n      let hexes = [],\n        view = new DataView(h);\n      for (let i = 0; i < view.byteLength; i += 4)\n        hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8));\n      return hexes.join('');\n    });",
    "description": "Creates a hash for a value using the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) algorithm.\nReturns a promise.\n\n- Use the [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) API to create a hash for the given value.\n- Create a new `TextEncoder` and use it to encode `val`. Pass its value to `SubtleCrypto.digest()` to generate a digest of the given data.\n- Use `DataView.prototype.getUint32()` to read data from the resolved `ArrayBuffer`.\n- Convert the data to it hexadecimal representation using `Number.prototype.toString(16)`. Add the data to an array using `Array.prototype.push()`.\n- Finally, use `Array.prototype.join()` to combine values in the array of `hexes` into a string.",
    "example": "hashBrowser(\n  JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })\n).then(console.log);\n// '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393'",
    "id": "hashBrowser",
    "tags": [
      "browser",
      "promise",
      "advanced"
    ]
  },
  {
    "code": "const crypto = require('crypto');\n\nconst hashNode = val =>\n  new Promise(resolve =>\n    setTimeout(\n      () => resolve(crypto.createHash('sha256').update(val).digest('hex')),\n      0\n    )\n  );",
    "description": "Creates a hash for a value using the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) algorithm.\nReturns a promise.\n\n- Use `crypto.createHash()` to create a `Hash` object with the appropriate algorithm.\n- Use `hash.update()` to add the data from `val` to the `Hash`, `hash.digest()` to calculate the digest of the data.\n- Use `setTimeout()` to prevent blocking on a long operation. Return a `Promise` to give it a familiar interface.",
    "example": "hashNode(JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })).then(\n  console.log\n);\n// '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393'",
    "id": "hashNode",
    "tags": [
      "node",
      "promise",
      "advanced"
    ]
  },
  {
    "code": "const haveSameContents = (a, b) => {\n  for (const v of new Set([...a, ...b]))\n    if (a.filter(e => e === v).length !== b.filter(e => e === v).length)\n      return false;\n  return true;\n};",
    "description": "Checks if two arrays contain the same elements regardless of order.\n\n- Use a `for...of` loop over a `Set` created from the values of both arrays.\n- Use `Array.prototype.filter()` to compare the amount of occurrences of each distinct value in both arrays.\n- Return `false` if the counts do not match for any element, `true` otherwise.",
    "example": "haveSameContents([1, 2, 4], [2, 4, 1]); // true",
    "id": "haveSameContents",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const head = arr => (arr && arr.length ? arr[0] : undefined);",
    "description": "Returns the head of an array.\n\n- Check if `arr` is truthy and has a `length` property.\n- Use `arr[0]` if possible to return the first element, otherwise return `undefined`.",
    "example": "head([1, 2, 3]); // 1\nhead([]); // undefined\nhead(null); // undefined\nhead(undefined); // undefined",
    "id": "head",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const heapsort = arr => {\n  const a = [...arr];\n  let l = a.length;\n\n  const heapify = (a, i) => {\n    const left = 2 * i + 1;\n    const right = 2 * i + 2;\n    let max = i;\n    if (left < l && a[left] > a[max]) max = left;\n    if (right < l && a[right] > a[max]) max = right;\n    if (max !== i) {\n      [a[max], a[i]] = [a[i], a[max]];\n      heapify(a, max);\n    }\n  };\n\n  for (let i = Math.floor(l / 2); i >= 0; i -= 1) heapify(a, i);\n  for (i = a.length - 1; i > 0; i--) {\n    [a[0], a[i]] = [a[i], a[0]];\n    l--;\n    heapify(a, 0);\n  }\n  return a;\n};",
    "description": "Sorts an array of numbers, using the heapsort algorithm.\n\n- Use recursion.\n- Use the spread operator (`...`) to clone the original array, `arr`.\n- Use closures to declare a variable, `l`, and a function `heapify`.\n- Use a `for` loop and `Math.floor()` in combination with `heapify` to create a max heap from the array.\n- Use a `for` loop to repeatedly narrow down the considered range, using `heapify` and swapping values as necessary in order to sort the cloned array.",
    "example": "heapsort([6, 3, 4, 1]); // [1, 3, 4, 6]",
    "id": "heapsort",
    "tags": [
      "algorithm",
      "array",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const hexToRGB = hex => {\n  let alpha = false,\n    h = hex.slice(hex.startsWith('#') ? 1 : 0);\n  if (h.length === 3) h = [...h].map(x => x + x).join('');\n  else if (h.length === 8) alpha = true;\n  h = parseInt(h, 16);\n  return (\n    'rgb' +\n    (alpha ? 'a' : '') +\n    '(' +\n    (h >>> (alpha ? 24 : 16)) +\n    ', ' +\n    ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +\n    ', ' +\n    ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +\n    (alpha ? \\`, \\${h & 0x000000ff}\\` : '') +\n    ')'\n  );\n};",
    "description": "Converts a color code to an `rgb()` or `rgba()` string if alpha value is provided.\n\n- Use bitwise right-shift operator and mask bits with `&` (and) operator to convert a hexadecimal color code (with or without prefixed with `#`) to a string with the RGB values.\n- If it's 3-digit color code, first convert to 6-digit version.\n- If an alpha value is provided alongside 6-digit hex, give `rgba()` string in return.",
    "example": "hexToRGB('#27ae60ff'); // 'rgba(39, 174, 96, 255)'\nhexToRGB('27ae60'); // 'rgb(39, 174, 96)'\nhexToRGB('#fff'); // 'rgb(255, 255, 255)'",
    "id": "hexToRGB",
    "tags": [
      "string",
      "math",
      "advanced"
    ]
  },
  {
    "code": "const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));",
    "description": "Hides all the elements specified.\n\n- Use the spread operator (`...`) and `Array.prototype.forEach()` to apply `display: none` to each element specified.",
    "example": "hide(...document.querySelectorAll('img')); // Hides all <img> elements on the page",
    "id": "hide",
    "tags": [
      "browser",
      "css",
      "beginner"
    ]
  },
  {
    "code": "const httpDelete = (url, callback, err = console.error) => {\n  const request = new XMLHttpRequest();\n  request.open('DELETE', url, true);\n  request.onload = () => callback(request);\n  request.onerror = () => err(request);\n  request.send();\n};",
    "description": "Makes a `DELETE` request to the passed URL.\n\n- Use the `XMLHttpRequest` web API to make a `DELETE` request to the given `url`.\n- Handle the `onload` event, by running the provided `callback` function.\n- Handle the `onerror` event, by running the provided `err` function.\n- Omit the third argument, `err` to log the request to the console's error stream by default.",
    "example": "httpDelete('https://jsonplaceholder.typicode.com/posts/1', request => {\n  console.log(request.responseText);\n}); // Logs: {}",
    "id": "httpDelete",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const httpGet = (url, callback, err = console.error) => {\n  const request = new XMLHttpRequest();\n  request.open('GET', url, true);\n  request.onload = () => callback(request.responseText);\n  request.onerror = () => err(request);\n  request.send();\n};",
    "description": "Makes a `GET` request to the passed URL.\n\n- Use the `XMLHttpRequest` web API to make a `GET` request to the given `url`.\n- Handle the `onload` event, by calling the given `callback` the `responseText`.\n- Handle the `onerror` event, by running the provided `err` function.\n- Omit the third argument, `err`, to log errors to the console's `error` stream by default.",
    "example": "httpGet(\n  'https://jsonplaceholder.typicode.com/posts/1',\n  console.log\n); /*\nLogs: {\n  \"userId\": 1,\n  \"id\": 1,\n  \"title\": \"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\",\n  \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"\n}\n*/",
    "id": "httpGet",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const httpPost = (url, data, callback, err = console.error) => {\n  const request = new XMLHttpRequest();\n  request.open('POST', url, true);\n  request.setRequestHeader('Content-type', 'application/json; charset=utf-8');\n  request.onload = () => callback(request.responseText);\n  request.onerror = () => err(request);\n  request.send(data);\n};",
    "description": "Makes a `POST` request to the passed URL.\n\n- Use the `XMLHttpRequest` web API to make a `POST` request to the given `url`.\n- Set the value of an `HTTP` request header with `setRequestHeader` method.\n- Handle the `onload` event, by calling the given `callback` the `responseText`.\n- Handle the `onerror` event, by running the provided `err` function.\n- Omit the fourth argument, `err`, to log errors to the console's `error` stream by default.",
    "example": "const newPost = {\n  userId: 1,\n  id: 1337,\n  title: 'Foo',\n  body: 'bar bar bar'\n};\nconst data = JSON.stringify(newPost);\nhttpPost(\n  'https://jsonplaceholder.typicode.com/posts',\n  data,\n  console.log\n); /*\nLogs: {\n  \"userId\": 1,\n  \"id\": 1337,\n  \"title\": \"Foo\",\n  \"body\": \"bar bar bar\"\n}\n*/\nhttpPost(\n  'https://jsonplaceholder.typicode.com/posts',\n  null, // does not send a body\n  console.log\n); /*\nLogs: {\n  \"id\": 101\n}\n*/",
    "id": "httpPost",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const httpPut = (url, data, callback, err = console.error) => {\n  const request = new XMLHttpRequest();\n  request.open('PUT', url, true);\n  request.setRequestHeader('Content-type', 'application/json; charset=utf-8');\n  request.onload = () => callback(request);\n  request.onerror = () => err(request);\n  request.send(data);\n};",
    "description": "Makes a `PUT` request to the passed URL.\n\n- Use `XMLHttpRequest` web api to make a `PUT` request to the given `url`.\n- Set the value of an `HTTP` request header with `setRequestHeader` method.\n- Handle the `onload` event, by running the provided `callback` function.\n- Handle the `onerror` event, by running the provided `err` function.\n- Omit the last argument, `err` to log the request to the console's error stream by default.",
    "example": "const password = 'fooBaz';\nconst data = JSON.stringify({\n  id: 1,\n  title: 'foo',\n  body: 'bar',\n  userId: 1\n});\nhttpPut('https://jsonplaceholder.typicode.com/posts/1', data, request => {\n  console.log(request.responseText);\n}); /*\nLogs: {\n  id: 1,\n  title: 'foo',\n  body: 'bar',\n  userId: 1\n}\n*/",
    "id": "httpPut",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const httpsRedirect = () => {\n  if (location.protocol !== 'https:')\n    location.replace('https://' + location.href.split('//')[1]);\n};",
    "description": "Redirects the page to HTTPS if it's currently in HTTP.\n\n- Use `location.protocol` to get the protocol currently being used.\n- If it's not HTTPS, use `location.replace()` to replace the existing page with the HTTPS version of the page.\n- Use `location.href` to get the full address, split it with `String.prototype.split()` and remove the protocol part of the URL.\n- Note that pressing the back button doesn't take it back to the HTTP page as its replaced in the history.",
    "example": "httpsRedirect(); \n// If you are on http://mydomain.com, you are redirected to https://mydomain.com",
    "id": "httpsRedirect",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const hz = (fn, iterations = 100) => {\n  const before = performance.now();\n  for (let i = 0; i < iterations; i++) fn();\n  return (1000 * iterations) / (performance.now() - before);\n};",
    "description": "Measures the number of times a function is executed per second (`hz`/`hertz`).\n\n- Use `performance.now()` to get the difference in milliseconds before and after the iteration loop to calculate the time elapsed executing the function `iterations` times.\n- Return the number of cycles per second by converting milliseconds to seconds and dividing it by the time elapsed.\n- Omit the second argument, `iterations`, to use the default of 100 iterations.",
    "example": "const numbers = Array(10000).fill().map((_, i) => i);\n\nconst sumReduce = () => numbers.reduce((acc, n) => acc + n, 0);\nconst sumForLoop = () => {\n  let sum = 0;\n  for (let i = 0; i < numbers.length; i++) sum += numbers[i];\n  return sum;\n};\n\nMath.round(hz(sumReduce)); // 572\nMath.round(hz(sumForLoop)); // 4784",
    "id": "hz",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const inRange = (n, start, end = null) => {\n  if (end && start > end) [end, start] = [start, end];\n  return end == null ? n >= 0 && n < start : n >= start && n < end;\n};",
    "description": "Checks if the given number falls within the given range.\n\n- Use arithmetic comparison to check if the given number is in the specified range.\n- If the second argument, `end`, is not specified, the range is considered to be from `0` to `start`.",
    "example": "inRange(3, 2, 5); // true\ninRange(3, 4); // true\ninRange(2, 3, 5); // false\ninRange(3, 2); // false",
    "id": "inRange",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const includesAll = (arr, values) => values.every(v => arr.includes(v));",
    "description": "Checks if all the elements in `values` are included in `arr`.\n\n- Use `Array.prototype.every()` and `Array.prototype.includes()` to check if all elements of `values` are included in `arr`.",
    "example": "includesAll([1, 2, 3, 4], [1, 4]); // true\nincludesAll([1, 2, 3, 4], [1, 5]); // false",
    "id": "includesAll",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const includesAny = (arr, values) => values.some(v => arr.includes(v));",
    "description": "Checks if at least one element of `values` is included in `arr`.\n\n- Use `Array.prototype.some()` and `Array.prototype.includes()` to check if at least one element of `values` is included in `arr`.",
    "example": "includesAny([1, 2, 3, 4], [2, 9]); // true\nincludesAny([1, 2, 3, 4], [8, 9]); // false",
    "id": "includesAny",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const indentString = (str, count, indent = ' ') =>\n  str.replace(/^/gm, indent.repeat(count));",
    "description": "Indents each line in the provided string.\n\n- Use `String.prototype.replace()` and a regular expression to add the character specified by `indent` `count` times at the start of each line.\n- Omit the third argument, `indent`, to use a default indentation character of `' '`.",
    "example": "indentString('Lorem\\nIpsum', 2); // '  Lorem\\n  Ipsum'\nindentString('Lorem\\nIpsum', 2, '_'); // '__Lorem\\n__Ipsum'",
    "id": "indentString",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const indexBy = (arr, fn) =>\n  arr.reduce((obj, v, i) => {\n    obj[fn(v, i, arr)] = v;\n    return obj;\n  }, {});",
    "description": "Creates an object from an array, using a function to map each value to a key.\n\n- Use `Array.prototype.reduce()` to create an object from `arr`.\n- Apply `fn` to each value of `arr` to produce a key and add the key-value pair to the object.",
    "example": "indexBy([\n  { id: 10, name: 'apple' },\n  { id: 20, name: 'orange' }\n], x => x.id);\n// { '10': { id: 10, name: 'apple' }, '20': { id: 20, name: 'orange' } }",
    "id": "indexBy",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const indexOfAll = (arr, val) =>\n  arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);",
    "description": "Finds all indexes of `val` in an array.\nIf `val` never occurs, returns an empty array.\n\n- Use `Array.prototype.reduce()` to loop over elements and store indexes for matching elements.",
    "example": "indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0, 3]\nindexOfAll([1, 2, 3], 4); // []",
    "id": "indexOfAll",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const indexOfSubstrings = function* (str, searchValue) {\n  let i = 0;\n  while (true) {\n    const r = str.indexOf(searchValue, i);\n    if (r !== -1) {\n      yield r;\n      i = r + 1;\n    } else return;\n  }\n};",
    "description": "Finds all the indexes of a substring in a given string.\n\n- Use `Array.prototype.indexOf()` to look for `searchValue` in `str`.\n- Use `yield` to return the index if the value is found and update the index, `i`.\n- Use a `while` loop that will terminate the generator as soon as the value returned from `Array.prototype.indexOf()` is `-1`.",
    "example": "[...indexOfSubstrings('tiktok tok tok tik tok tik', 'tik')]; // [0, 15, 23]\n[...indexOfSubstrings('tutut tut tut', 'tut')]; // [0, 2, 6, 10]\n[...indexOfSubstrings('hello', 'hi')]; // []",
    "id": "indexOfSubstrings",
    "tags": [
      "string",
      "algorithm",
      "generator",
      "intermediate"
    ]
  },
  {
    "code": "const indexOn = (arr, key) =>\n  arr.reduce((obj, v) => {\n    const { [key]: id, ...data } = v;\n    obj[id] = data;\n    return obj;\n  }, {});",
    "description": "Creates an object from an array, using the specified key and excluding it from each value.\n\n- Use `Array.prototype.reduce()` to create an object from `arr`.\n- Use object destructuring to get the value of the given `key` and the associated `data` and add the key-value pair to the object.",
    "example": "indexOn([\n  { id: 10, name: 'apple' },\n  { id: 20, name: 'orange' }\n], 'id');\n// { '10': { name: 'apple' }, '20': { name: 'orange' } }",
    "id": "indexOn",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const initial = arr => arr.slice(0, -1);",
    "description": "Returns all the elements of an array except the last one.\n\n- Use `Array.prototype.slice(0, -1)` to return all but the last element of the array.",
    "example": "initial([1, 2, 3]); // [1, 2]",
    "id": "initial",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const initialize2DArray = (w, h, val = null) =>\n  Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));",
    "description": "Initializes a 2D array of given width and height and value.\n\n- Use `Array.from()` and `Array.prototype.map()` to generate `h` rows where each is a new array of size `w`.\n- Use `Array.prototype.fill()` to initialize all items with value `val`.\n- Omit the last argument, `val`, to use a default value of `null`.",
    "example": "initialize2DArray(2, 2, 0); // [[0, 0], [0, 0]]",
    "id": "initialize2DArray",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const initializeArrayWithRange = (end, start = 0, step = 1) =>\n  Array.from(\n    { length: Math.ceil((end - start + 1) / step) },\n    (_, i) => i * step + start\n  );",
    "description": "Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive with their common difference `step`.\n\n- Use `Array.from()` to create an array of the desired length.\n- Use `(end - start + 1)/step` and a map function to fill the array with the desired values in the given range.\n- Omit the second argument, `start`, to use a default value of `0`.\n- Omit the last argument, `step`, to use a default value of `1`.",
    "example": "initializeArrayWithRange(5); // [0, 1, 2, 3, 4, 5]\ninitializeArrayWithRange(7, 3); // [3, 4, 5, 6, 7]\ninitializeArrayWithRange(9, 0, 2); // [0, 2, 4, 6, 8]",
    "id": "initializeArrayWithRange",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const initializeArrayWithRangeRight = (end, start = 0, step = 1) =>\n  Array.from({ length: Math.ceil((end + 1 - start) / step) }).map(\n    (v, i, arr) => (arr.length - i - 1) * step + start\n  );",
    "description": "Initializes an array containing the numbers in the specified range (in reverse) where `start` and `end` are inclusive with their common difference `step`.\n\n- Use `Array.from(Math.ceil((end+1-start)/step))` to create an array of the desired length(the amounts of elements is equal to `(end-start)/step` or `(end+1-start)/step` for inclusive end), `Array.prototype.map()` to fill with the desired values in a range.\n- Omit the second argument, `start`, to use a default value of `0`.\n- Omit the last argument, `step`, to use a default value of `1`.",
    "example": "initializeArrayWithRangeRight(5); // [5, 4, 3, 2, 1, 0]\ninitializeArrayWithRangeRight(7, 3); // [7, 6, 5, 4, 3]\ninitializeArrayWithRangeRight(9, 0, 2); // [8, 6, 4, 2, 0]",
    "id": "initializeArrayWithRangeRight",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const initializeArrayWithValues = (n, val = 0) =>\n  Array.from({ length: n }).fill(val);",
    "description": "Initializes and fills an array with the specified values.\n\n- Use `Array.from()` to create an array of the desired length, `Array.prototype.fill()` to fill it with the desired values.\n- Omit the last argument, `val`, to use a default value of `0`.",
    "example": "initializeArrayWithValues(5, 2); // [2, 2, 2, 2, 2]",
    "id": "initializeArrayWithValues",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const initializeNDArray = (val, ...args) =>\n  args.length === 0\n    ? val\n    : Array.from({ length: args[0] }).map(() =>\n        initializeNDArray(val, ...args.slice(1))\n      );",
    "description": "Create a n-dimensional array with given value.\n\n- Use recursion.\n- Use `Array.from()`, `Array.prototype.map()` to generate rows where each is a new array initialized using `initializeNDArray()`.",
    "example": "initializeNDArray(1, 3); // [1, 1, 1]\ninitializeNDArray(5, 2, 2, 2); // [[[5, 5], [5, 5]], [[5, 5], [5, 5]]]",
    "id": "initializeNDArray",
    "tags": [
      "array",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const injectCSS = css => {\n  let el = document.createElement('style');\n  el.type = 'text/css';\n  el.innerText = css;\n  document.head.appendChild(el);\n  return el;\n};",
    "description": "Injects the given CSS code into the current document\n\n- Use `Document.createElement()` to create a new `style` element and set its type to `text/css`.\n- Use `Element.innerText` to set the value to the given CSS string.\n- Use `Document.head` and `Element.appendChild()` to append the new element to the document head.\n- Return the newly created `style` element.",
    "example": "injectCSS('body { background-color: #000 }'); \n// '<style type=\"text/css\">body { background-color: #000 }</style>'",
    "id": "injectCSS",
    "tags": [
      "browser",
      "css",
      "intermediate"
    ]
  },
  {
    "code": "const insertAfter = (el, htmlString) =>\n  el.insertAdjacentHTML('afterend', htmlString);",
    "description": "Inserts an HTML string after the end of the specified element.\n\n- Use `Element.insertAdjacentHTML()` with a position of `'afterend'` to parse `htmlString` and insert it after the end of `el`.",
    "example": "insertAfter(document.getElementById('myId'), '<p>after</p>');\n// <div id=\"myId\">...</div> <p>after</p>",
    "id": "insertAfter",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const insertAt = (arr, i, ...v) => {\n  arr.splice(i + 1, 0, ...v);\n  return arr;\n};",
    "description": "Mutates the original array to insert the given values after the specified index.\n\n- Use `Array.prototype.splice()` with an appropriate index and a delete count of `0`, spreading the given values to be inserted.",
    "example": "let myArray = [1, 2, 3, 4];\ninsertAt(myArray, 2, 5); // myArray = [1, 2, 3, 5, 4]\n\nlet otherArray = [2, 10];\ninsertAt(otherArray, 0, 4, 6, 8); // otherArray = [2, 4, 6, 8, 10]",
    "id": "insertAt",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const insertBefore = (el, htmlString) =>\n  el.insertAdjacentHTML('beforebegin', htmlString);",
    "description": "Inserts an HTML string before the start of the specified element.\n\n- Use `Element.insertAdjacentHTML()` with a position of `'beforebegin'` to parse `htmlString` and insert it before the start of `el`.",
    "example": "insertBefore(document.getElementById('myId'), '<p>before</p>');\n// <p>before</p> <div id=\"myId\">...</div>",
    "id": "insertBefore",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const insertionSort = arr =>\n  arr.reduce((acc, x) => {\n    if (!acc.length) return [x];\n    acc.some((y, j) => {\n      if (x <= y) {\n        acc.splice(j, 0, x);\n        return true;\n      }\n      if (x > y && j === acc.length - 1) {\n        acc.splice(j + 1, 0, x);\n        return true;\n      }\n      return false;\n    });\n    return acc;\n  }, []);",
    "description": "Sorts an array of numbers, using the insertion sort algorithm.\n\n- Use `Array.prototype.reduce()` to iterate over all the elements in the given array.\n- If the `length` of the accumulator is `0`, add the current element to it.\n- Use `Array.prototype.some()` to iterate over the results in the accumulator until the correct position is found.\n- Use `Array.prototype.splice()` to insert the current element into the accumulator.",
    "example": "insertionSort([6, 3, 4, 1]); // [1, 3, 4, 6]",
    "id": "insertionSort",
    "tags": [
      "algorithm",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const intersection = (a, b) => {\n  const s = new Set(b);\n  return [...new Set(a)].filter(x => s.has(x));\n};",
    "description": "Returns the elements that exist in both arrays, filtering duplicate values.\n\n- Create a `Set` from `b`, then use `Array.prototype.filter()` on `a` to only keep values contained in `b`.",
    "example": "intersection([1, 2, 3], [4, 3, 2]); // [2, 3]",
    "id": "intersection",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const intersectionBy = (a, b, fn) => {\n  const s = new Set(b.map(fn));\n  return [...new Set(a)].filter(x => s.has(fn(x)));\n};",
    "description": "Returns the elements that exist in both arrays, after applying the provided function to each array element of both.\n\n- Create a `Set` by applying `fn` to all elements in `b`.\n- Use `Array.prototype.filter()` on `a` to only keep elements, which produce values contained in `b` when `fn` is applied to them.",
    "example": "intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1]\nintersectionBy(\n  [{ title: 'Apple' }, { title: 'Orange' }],\n  [{ title: 'Orange' }, { title: 'Melon' }],\n  x => x.title\n); // [{ title: 'Orange' }]",
    "id": "intersectionBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const intersectionWith = (a, b, comp) =>\n  a.filter(x => b.findIndex(y => comp(x, y)) !== -1);",
    "description": "Returns the elements that exist in both arrays, using a provided comparator function.\n\n- Use `Array.prototype.filter()` and `Array.prototype.findIndex()` in combination with the provided comparator to determine intersecting values.",
    "example": "intersectionWith(\n  [1, 1.2, 1.5, 3, 0],\n  [1.9, 3, 0, 3.9],\n  (a, b) => Math.round(a) === Math.round(b)\n); // [1.5, 3, 0]",
    "id": "intersectionWith",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const invertKeyValues = (obj, fn) =>\n  Object.keys(obj).reduce((acc, key) => {\n    const val = fn ? fn(obj[key]) : obj[key];\n    acc[val] = acc[val] || [];\n    acc[val].push(key);\n    return acc;\n  }, {});",
    "description": "Inverts the key-value pairs of an object, without mutating it. \n\n- Use `Object.keys()` and `Array.prototype.reduce()` to invert the key-value pairs of an object and apply the function provided (if any).\n- Omit the second argument, `fn`, to get the inverted keys without applying a function to them.\n- The corresponding inverted value of each inverted key is an array of keys responsible for generating the inverted value. If a function is supplied, it is applied to each inverted key.",
    "example": "invertKeyValues({ a: 1, b: 2, c: 1 }); // { 1: [ 'a', 'c' ], 2: [ 'b' ] }\ninvertKeyValues({ a: 1, b: 2, c: 1 }, value => 'group' + value);\n// { group1: [ 'a', 'c' ], group2: [ 'b' ] }",
    "id": "invertKeyValues",
    "tags": [
      "object",
      "advanced"
    ]
  },
  {
    "code": "const is = (type, val) => ![, null].includes(val) && val.constructor === type;",
    "description": "Checks if the provided value is of the specified type.\n\n- Ensure the value is not `undefined` or `null` using `Array.prototype.includes()`.\n- Compare the `constructor` property on the value with `type` to check if the provided value is of the specified `type`.",
    "example": "is(Array, [1]); // true\nis(ArrayBuffer, new ArrayBuffer()); // true\nis(Map, new Map()); // true\nis(RegExp, /./g); // true\nis(Set, new Set()); // true\nis(WeakMap, new WeakMap()); // true\nis(WeakSet, new WeakSet()); // true\nis(String, ''); // true\nis(String, new String('')); // true\nis(Number, 1); // true\nis(Number, new Number(1)); // true\nis(Boolean, true); // true\nis(Boolean, new Boolean(true)); // true",
    "id": "is",
    "tags": [
      "type",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);",
    "description": "Checks if the given string is an absolute URL.\n\n- Use `RegExp.prototype.test()` to test if the string is an absolute URL.",
    "example": "isAbsoluteURL('https://google.com'); // true\nisAbsoluteURL('ftp://www.myserver.net'); // true\nisAbsoluteURL('/foo/bar'); // false",
    "id": "isAbsoluteURL",
    "tags": [
      "string",
      "browser",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const isAfterDate = (dateA, dateB) => dateA > dateB;",
    "description": "Checks if a date is after another date.\n\n- Use the greater than operator (`>`) to check if the first date comes after the second one.",
    "example": "isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true",
    "id": "isAfterDate",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isAlpha = str => /^[a-zA-Z]*$/.test(str);",
    "description": "Checks if a string contains only alpha characters.\n\n- Use `RegExp.prototype.test()` to check if the given string matches against the alphabetic regexp pattern.",
    "example": "isAlpha('sampleInput'); // true\nisAlpha('this Will fail'); // false\nisAlpha('123'); // false",
    "id": "isAlpha",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const isAlphaNumeric = str => /^[a-z0-9]+$/gi.test(str);",
    "description": "Checks if a string contains only alphanumeric characters.\n\n- Use `RegExp.prototype.test()` to check if the input string matches against the alphanumeric regexp pattern.",
    "example": "isAlphaNumeric('hello123'); // true\nisAlphaNumeric('123'); // true\nisAlphaNumeric('hello 123'); // false (space character is not alphanumeric)\nisAlphaNumeric('#$hello'); // false",
    "id": "isAlphaNumeric",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const isAnagram = (str1, str2) => {\n  const normalize = str =>\n    str\n      .toLowerCase()\n      .replace(/[^a-z0-9]/gi, '')\n      .split('')\n      .sort()\n      .join('');\n  return normalize(str1) === normalize(str2);\n};",
    "description": "Checks if a string is an anagram of another string (case-insensitive, ignores spaces, punctuation and special characters).\n\n- Use `String.prototype.toLowerCase()` and `String.prototype.replace()` with an appropriate regular expression to remove unnecessary characters.\n- Use `String.prototype.split('')`, `Array.prototype.sort()` and `Array.prototype.join('')` on both strings to normalize them, then check if their normalized forms are equal.",
    "example": "isAnagram('iceman', 'cinema'); // true",
    "id": "isAnagram",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const isArrayLike = obj =>\n  obj != null && typeof obj[Symbol.iterator] === 'function';",
    "description": "Checks if the provided argument is array-like (i.e. is iterable).\n\n- Check if the provided argument is not `null` and that its `Symbol.iterator` property is a function.",
    "example": "isArrayLike([1, 2, 3]); // true\nisArrayLike(document.querySelectorAll('.className')); // true\nisArrayLike('abc'); // true\nisArrayLike(null); // false",
    "id": "isArrayLike",
    "tags": [
      "type",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const isAsyncFunction = val =>\n  Object.prototype.toString.call(val) === '[object AsyncFunction]';",
    "description": "Checks if the given argument is an `async` function.\n\n- Use `Object.prototype.toString()` and `Function.prototype.call()` and check if the result is `'[object AsyncFunction]'`.",
    "example": "isAsyncFunction(function() {}); // false\nisAsyncFunction(async function() {}); // true",
    "id": "isAsyncFunction",
    "tags": [
      "type",
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const isBeforeDate = (dateA, dateB) => dateA < dateB;",
    "description": "Checks if a date is before another date.\n\n- Use the less than operator (`<`) to check if the first date comes before the second one.",
    "example": "isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true",
    "id": "isBeforeDate",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isBetweenDates = (dateStart, dateEnd, date) =>\n  date > dateStart && date < dateEnd;",
    "description": "Checks if a date is between two other dates.\n\n- Use the greater than (`>`) and less than (`<`) operators to check if `date` is between `dateStart` and `dateEnd`.",
    "example": "isBetweenDates(\n  new Date(2010, 11, 20),\n  new Date(2010, 11, 30),\n  new Date(2010, 11, 19)\n); // false\nisBetweenDates(\n  new Date(2010, 11, 20),\n  new Date(2010, 11, 30),\n  new Date(2010, 11, 25)\n); // true",
    "id": "isBetweenDates",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isBoolean = val => typeof val === 'boolean';",
    "description": "Checks if the given argument is a native boolean element.\n\n- Use `typeof` to check if a value is classified as a boolean primitive.",
    "example": "isBoolean(null); // false\nisBoolean(false); // true",
    "id": "isBoolean",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const isBrowser = () => ![typeof window, typeof document].includes('undefined');",
    "description": "Determines if the current runtime environment is a browser so that front-end modules can run on the server (Node) without throwing errors.\n\n- Use `Array.prototype.includes()` on the `typeof` values of both `window` and `document` (globals usually only available in a browser environment unless they were explicitly defined), which will return `true` if one of them is `undefined`.\n- `typeof` allows globals to be checked for existence without throwing a `ReferenceError`.\n- If both of them are not `undefined`, then the current environment is assumed to be a browser.",
    "example": "isBrowser(); // true (browser)\nisBrowser(); // false (Node)",
    "id": "isBrowser",
    "tags": [
      "browser",
      "node",
      "intermediate"
    ]
  },
  {
    "code": "const isBrowserTabFocused = () => !document.hidden;",
    "description": "Checks if the browser tab of the page is focused.\n\n- Use the `Document.hidden` property, introduced by the [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) to check if the browser tab of the page is visible or hidden.",
    "example": "isBrowserTabFocused(); // true",
    "id": "isBrowserTabFocused",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const isContainedIn = (a, b) => {\n  for (const v of new Set(a)) {\n    if (\n      !b.some(e => e === v) ||\n      a.filter(e => e === v).length > b.filter(e => e === v).length\n    )\n      return false;\n  }\n  return true;\n};",
    "description": "Checks if the elements of the first array are contained in the second one regardless of order.\n\n- Use a `for...of` loop over a `Set` created from the first array.\n- Use `Array.prototype.some()` to check if all distinct values are contained in the second array.\n- Use `Array.prototype.filter()` to compare the number of occurrences of each distinct value in both arrays.\n- Return `false` if the count of any element is greater in the first array than the second one, `true` otherwise.",
    "example": "isContainedIn([1, 4], [2, 4, 1]); // true",
    "id": "isContainedIn",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const isDateValid = (...val) => !Number.isNaN(new Date(...val).valueOf());",
    "description": "Checks if a valid date object can be created from the given values.\n\n- Use the spread operator (`...`) to pass the array of arguments to the `Date` constructor.\n- Use `Date.prototype.valueOf()` and `Number.isNaN()` to check if a valid `Date` object can be created from the given values.",
    "example": "isDateValid('December 17, 1995 03:24:00'); // true\nisDateValid('1995-12-17T03:24:00'); // true\nisDateValid('1995-12-17 T03:24:00'); // false\nisDateValid('Duck'); // false\nisDateValid(1995, 11, 17); // true\nisDateValid(1995, 11, 17, 'Duck'); // false\nisDateValid({}); // false",
    "id": "isDateValid",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const isDeepFrozen = obj =>\n  Object.isFrozen(obj) &&\n  Object.keys(obj).every(\n    prop => typeof obj[prop] !== 'object' || isDeepFrozen(obj[prop])\n  );",
    "description": "Checks if an object is deeply frozen.\n\n- Use recursion.\n- Use `Object.isFrozen()` on the given object.\n- Use `Object.keys()`, `Array.prototype.every()` to check that all keys are either deeply frozen objects or non-object values.",
    "example": "const x = Object.freeze({ a: 1 });\nconst y = Object.freeze({ b: { c: 2 } });\nisDeepFrozen(x); // true\nisDeepFrozen(y); // false",
    "id": "isDeepFrozen",
    "tags": [
      "object",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const isDisjoint = (a, b) => {\n  const sA = new Set(a), sB = new Set(b);\n  return [...sA].every(v => !sB.has(v));\n};",
    "description": "Checks if the two iterables are disjointed (have no common values).\n\n- Use the `new Set()` constructor to create a new `Set` object from each iterable.\n- Use `Array.prototype.every()` and `Set.prototype.has()` to check that the two iterables have no common values.",
    "example": "isDisjoint(new Set([1, 2]), new Set([3, 4])); // true\nisDisjoint(new Set([1, 2]), new Set([1, 3])); // false",
    "id": "isDisjoint",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const isDivisible = (dividend, divisor) => dividend % divisor === 0;",
    "description": "Checks if the first numeric argument is divisible by the second one.\n\n- Use the modulo operator (`%`) to check if the remainder is equal to `0`.",
    "example": "isDivisible(6, 3); // true",
    "id": "isDivisible",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const isDuplexStream = val =>\n  val !== null &&\n  typeof val === 'object' &&\n  typeof val.pipe === 'function' &&\n  typeof val._read === 'function' &&\n  typeof val._readableState === 'object' &&\n  typeof val._write === 'function' &&\n  typeof val._writableState === 'object';",
    "description": "Checks if the given argument is a duplex (readable and writable) stream.\n\n- Check if the value is different from `null`.\n- Use `typeof` to check if a value is of type `object` and the `pipe` property is of type `function`.\n- Additionally check if the `typeof` the `_read`, `_write` and `_readableState`, `_writableState` properties are `function` and `object` respectively.",
    "example": "const Stream = require('stream');\n\nisDuplexStream(new Stream.Duplex()); // true",
    "id": "isDuplexStream",
    "tags": [
      "node",
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const isEmpty = val => val == null || !(Object.keys(val) || val).length;",
    "description": "Checks if the a value is an empty object/collection, has no enumerable properties or is any type that is not considered a collection.\n\n- Check if the provided value is `null` or if its `length` is equal to `0`.",
    "example": "isEmpty([]); // true\nisEmpty({}); // true\nisEmpty(''); // true\nisEmpty([1, 2]); // false\nisEmpty({ a: 1, b: 2 }); // false\nisEmpty('text'); // false\nisEmpty(123); // true - type is not considered a collection\nisEmpty(true); // true - type is not considered a collection",
    "id": "isEmpty",
    "tags": [
      "type",
      "array",
      "object",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const isEven = num => num % 2 === 0;",
    "description": "Checks if the given number is even.\n\n- Checks whether a number is odd or even using the modulo (`%`) operator.\n- Returns `true` if the number is even, `false` if the number is odd.",
    "example": "isEven(3); // false",
    "id": "isEven",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const isFunction = val => typeof val === 'function';",
    "description": "Checks if the given argument is a function.\n\n- Use `typeof` to check if a value is classified as a function primitive.",
    "example": "isFunction('x'); // false\nisFunction(x => x); // true",
    "id": "isFunction",
    "tags": [
      "type",
      "function",
      "beginner"
    ]
  },
  {
    "code": "const isGeneratorFunction = val =>\n  Object.prototype.toString.call(val) === '[object GeneratorFunction]';",
    "description": "Checks if the given argument is a generator function.\n\n- Use `Object.prototype.toString()` and `Function.prototype.call()` and check if the result is `'[object GeneratorFunction]'`.",
    "example": "isGeneratorFunction(function() {}); // false\nisGeneratorFunction(function*() {}); // true",
    "id": "isGeneratorFunction",
    "tags": [
      "type",
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const isISOString = val => {\n  const d = new Date(val);\n  return !Number.isNaN(d.valueOf()) && d.toISOString() === val;\n};",
    "description": "Checks if the given string is valid in the simplified extended ISO format (ISO 8601).\n\n- Use `new Date()` to create a date object from the given string.\n- Use `Date.prototype.valueOf()` and `Number.isNaN()` to check if the produced date object is valid.\n- Use `Date.prototype.toISOString()` to compare the ISO formatted string representation of the date with the original string.",
    "example": "isISOString('2020-10-12T10:10:10.000Z'); // true\nisISOString('2020-10-12'); // false",
    "id": "isISOString",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const isLeapYear = year => new Date(year, 1, 29).getMonth() === 1;",
    "description": "Checks if the given `year` is a leap year.\n\n- Use `new Date()`, setting the date to February 29th of the given `year`.\n- Use `Date.prototype.getMonth()` to check if the month is equal to `1`.",
    "example": "isLeapYear(2019); // false\nisLeapYear(2020); // true",
    "id": "isLeapYear",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isLocalStorageEnabled = () => {\n  try {\n    const key = \\`__storage__test\\`;\n    window.localStorage.setItem(key, null);\n    window.localStorage.removeItem(key);\n    return true;\n  } catch (e) {\n    return false;\n  }\n};",
    "description": "Checks if `localStorage` is enabled.\n\n- Use a `try...catch` block to return `true` if all operations complete successfully, `false` otherwise.\n- Use `Storage.setItem()` and `Storage.removeItem()` to test storing and deleting a value in `window.localStorage`.",
    "example": "isLocalStorageEnabled(); // true, if localStorage is accessible",
    "id": "isLocalStorageEnabled",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const isLowerCase = str => str === str.toLowerCase();",
    "description": "Checks if a string is lower case.\n\n- Convert the given string to lower case, using `String.prototype.toLowerCase()` and compare it to the original.",
    "example": "isLowerCase('abc'); // true\nisLowerCase('a3@$'); // true\nisLowerCase('Ab4'); // false",
    "id": "isLowerCase",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const isNegativeZero = val => val === 0 && 1 / val === -Infinity;",
    "description": "Checks if the given value is equal to negative zero (`-0`).\n\n- Check whether a passed value is equal to `0` and if `1` divided by the value equals `-Infinity`.",
    "example": "isNegativeZero(-0); // true\nisNegativeZero(0); // false",
    "id": "isNegativeZero",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const isNil = val => val === undefined || val === null;",
    "description": "Checks if the specified value is `null` or `undefined`.\n\n- Use the strict equality operator to check if the value of `val` is equal to `null` or `undefined`.",
    "example": "isNil(null); // true\nisNil(undefined); // true\nisNil(''); // false",
    "id": "isNil",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const isNode = () =>\n  typeof process !== 'undefined' &&\n  !!process.versions &&\n  !!process.versions.node;",
    "description": "Determines if the current runtime environment is Node.js.\n\n- Use the `process` global object that provides information about the current Node.js process.\n- Check if `process`, `process.versions` and `process.versions.node` are defined.",
    "example": "isNode(); // true (Node)\nisNode(); // false (browser)",
    "id": "isNode",
    "tags": [
      "node",
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const isNull = val => val === null;",
    "description": "Checks if the specified value is `null`.\n\n- Use the strict equality operator to check if the value of `val` is equal to `null`.",
    "example": "isNull(null); // true",
    "id": "isNull",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const isNumber = val => typeof val === 'number' && val === val;",
    "description": "Checks if the given argument is a number.\n\n- Use `typeof` to check if a value is classified as a number primitive.\n- To safeguard against `NaN`, check if `val === val` (as `NaN` has a `typeof` equal to `number` and is the only value not equal to itself).",
    "example": "isNumber(1); // true\nisNumber('1'); // false\nisNumber(NaN); // false",
    "id": "isNumber",
    "tags": [
      "type",
      "math",
      "beginner"
    ]
  },
  {
    "code": "const isObject = obj => obj === Object(obj);",
    "description": "Checks if the passed value is an object or not.\n\n- Uses the `Object` constructor to create an object wrapper for the given value.\n- If the value is `null` or `undefined`, create and return an empty object.\n- Otherwise, return an object of a type that corresponds to the given value.",
    "example": "isObject([1, 2, 3, 4]); // true\nisObject([]); // true\nisObject(['Hello!']); // true\nisObject({ a: 1 }); // true\nisObject({}); // true\nisObject(true); // false",
    "id": "isObject",
    "tags": [
      "type",
      "object",
      "beginner"
    ]
  },
  {
    "code": "const isObjectLike = val => val !== null && typeof val === 'object';",
    "description": "Checks if a value is object-like.\n\n- Check if the provided value is not `null` and its `typeof` is equal to `'object'`.",
    "example": "isObjectLike({}); // true\nisObjectLike([1, 2, 3]); // true\nisObjectLike(x => x); // false\nisObjectLike(null); // false",
    "id": "isObjectLike",
    "tags": [
      "type",
      "object",
      "beginner"
    ]
  },
  {
    "code": "const isOdd = num => num % 2 === 1;",
    "description": "Checks if the given number is odd.\n\n- Check whether a number is odd or even using the modulo (`%`) operator.\n- Return `true` if the number is odd, `false` if the number is even.",
    "example": "isOdd(3); // true",
    "id": "isOdd",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const isPlainObject = val =>\n  !!val && typeof val === 'object' && val.constructor === Object;",
    "description": "Checks if the provided value is an object created by the Object constructor.\n\n- Check if the provided value is truthy.\n- Use `typeof` to check if it is an object and `Object.prototype.constructor` to make sure the constructor is equal to `Object`.",
    "example": "isPlainObject({ a: 1 }); // true\nisPlainObject(new Map()); // false",
    "id": "isPlainObject",
    "tags": [
      "type",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const isPowerOfTen = n => Math.log10(n) % 1 === 0;",
    "description": "Checks if the given number is a power of `10`.\n\n- Use `Math.log10()` and the modulo operator (`%`) to determine if `n` is a power of `10`.",
    "example": "isPowerOfTen(1); // true\nisPowerOfTen(10); // true\nisPowerOfTen(20); // false",
    "id": "isPowerOfTen",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const isPowerOfTwo = n => !!n && (n & (n - 1)) == 0;",
    "description": "Checks if the given number is a power of `2`.\n\n- Use the bitwise binary AND operator (`&`) to determine if `n` is a power of `2`.\n- Additionally, check that `n` is not falsy.",
    "example": "isPowerOfTwo(0); // false\nisPowerOfTwo(1); // true\nisPowerOfTwo(8); // true",
    "id": "isPowerOfTwo",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const isPrime = num => {\n  const boundary = Math.floor(Math.sqrt(num));\n  for (let i = 2; i <= boundary; i++) if (num % i === 0) return false;\n  return num >= 2;\n};",
    "description": "Checks if the provided integer is a prime number.\n\n- Check numbers from `2` to the square root of the given number.\n- Return `false` if any of them divides the given number, else return `true`, unless the number is less than `2`.",
    "example": "isPrime(11); // true",
    "id": "isPrime",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const isPrimitive = val => Object(val) !== val;",
    "description": "Checks if the passed value is primitive or not.\n\n- Create an object from `val` and compare it with `val` to determine if the passed value is primitive (i.e. not equal to the created object).",
    "example": "isPrimitive(null); // true\nisPrimitive(undefined); // true\nisPrimitive(50); // true\nisPrimitive('Hello!'); // true\nisPrimitive(false); // true\nisPrimitive(Symbol()); // true\nisPrimitive([]); // false\nisPrimitive({}); // false",
    "id": "isPrimitive",
    "tags": [
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const isPromiseLike = obj =>\n  obj !== null &&\n  (typeof obj === 'object' || typeof obj === 'function') &&\n  typeof obj.then === 'function';",
    "description": "Checks if an object looks like a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n\n- Check if the object is not `null`, its `typeof` matches either `object` or `function` and if it has a `.then` property, which is also a `function`.",
    "example": "isPromiseLike({\n  then: function() {\n    return '';\n  }\n}); // true\nisPromiseLike(null); // false\nisPromiseLike({}); // false",
    "id": "isPromiseLike",
    "tags": [
      "type",
      "function",
      "promise",
      "intermediate"
    ]
  },
  {
    "code": "const isReadableStream = val =>\n  val !== null &&\n  typeof val === 'object' &&\n  typeof val.pipe === 'function' &&\n  typeof val._read === 'function' &&\n  typeof val._readableState === 'object';",
    "description": "Checks if the given argument is a readable stream.\n\n- Check if the value is different from `null`.\n- Use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`.\n- Additionally check if the `typeof` the `_read` and `_readableState` properties are `function` and `object` respectively.",
    "example": "const fs = require('fs');\n\nisReadableStream(fs.createReadStream('test.txt')); // true",
    "id": "isReadableStream",
    "tags": [
      "node",
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const isSameDate = (dateA, dateB) =>\n  dateA.toISOString() === dateB.toISOString();",
    "description": "Checks if a date is the same as another date.\n\n- Use `Date.prototype.toISOString()` and strict equality checking (`===`) to check if the first date is the same as the second one.",
    "example": "isSameDate(new Date(2010, 10, 20), new Date(2010, 10, 20)); // true",
    "id": "isSameDate",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isSameOrigin = (origin, destination) =>\n  origin.protocol === destination.protocol && origin.host === destination.host;",
    "description": "Checks if two URLs are on the same origin.\n\n- Use `URL.protocol` and `URL.host` to check if both URLs have the same protocol and host.",
    "example": "const origin = new URL('https://www.30secondsofcode.org/about');\nconst destination = new URL('https://www.30secondsofcode.org/contact');\nisSameOrigin(origin, destination); // true\nconst other = new URL('https://developer.mozilla.org);\nisSameOrigin(origin, other); // false",
    "id": "isSameOrigin",
    "tags": [
      "object",
      "beginner"
    ]
  },
  {
    "code": "const isSessionStorageEnabled = () => {\n  try {\n    const key = \\`__storage__test\\`;\n    window.sessionStorage.setItem(key, null);\n    window.sessionStorage.removeItem(key);\n    return true;\n  } catch (e) {\n    return false;\n  }\n};",
    "description": "Checks if `sessionStorage` is enabled.\n\n- Use a `try...catch` block to return `true` if all operations complete successfully, `false` otherwise.\n- Use `Storage.setItem()` and `Storage.removeItem()` to test storing and deleting a value in `window.sessionStorage`.",
    "example": "isSessionStorageEnabled(); // true, if sessionStorage is accessible",
    "id": "isSessionStorageEnabled",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const isSorted = arr => {\n  if (arr.length <= 1) return 0;\n  const direction = arr[1] - arr[0];\n  for (let i = 2; i < arr.length; i++) {\n    if ((arr[i] - arr[i - 1]) * direction < 0) return 0;\n  }\n  return Math.sign(direction);\n};",
    "description": "Checks if a numeric array is sorted.\n\n- Calculate the ordering `direction` for the first pair of adjacent array elements.\n- Return `0` if the given array is empty, only has one element or the `direction` changes for any pair of adjacent array elements.\n- Use `Math.sign()` to covert the final value of `direction` to `-1` (descending order) or `1` (ascending order).",
    "example": "isSorted([0, 1, 2, 2]); // 1\nisSorted([4, 3, 2]); // -1\nisSorted([4, 3, 5]); // 0\nisSorted([4]); // 0",
    "id": "isSorted",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const isStream = val =>\n  val !== null && typeof val === 'object' && typeof val.pipe === 'function';",
    "description": "Checks if the given argument is a stream.\n\n- Check if the value is different from `null`.\n- Use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`.",
    "example": "const fs = require('fs');\n\nisStream(fs.createReadStream('test.txt')); // true",
    "id": "isStream",
    "tags": [
      "node",
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const isString = val => typeof val === 'string';",
    "description": "Checks if the given argument is a string.\nOnly works for string primitives.\n\n- Use `typeof` to check if a value is classified as a string primitive.",
    "example": "isString('10'); // true",
    "id": "isString",
    "tags": [
      "type",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const isSymbol = val => typeof val === 'symbol';",
    "description": "Checks if the given argument is a symbol.\n\n- Use `typeof` to check if a value is classified as a symbol primitive.",
    "example": "isSymbol(Symbol('x')); // true",
    "id": "isSymbol",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;",
    "description": "Checks if the current environment is [Travis CI](https://travis-ci.org/).\n\n- Check if the current environment has the `TRAVIS` and `CI` environment variables ([reference](https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables)).",
    "example": "isTravisCI(); // true (if code is running on Travis CI)",
    "id": "isTravisCI",
    "tags": [
      "node",
      "intermediate"
    ]
  },
  {
    "code": "const isUndefined = val => val === undefined;",
    "description": "Checks if the specified value is `undefined`.\n\n- Use the strict equality operator to check if `val` is equal to `undefined`.",
    "example": "isUndefined(undefined); // true",
    "id": "isUndefined",
    "tags": [
      "type",
      "beginner"
    ]
  },
  {
    "code": "const isUpperCase = str => str === str.toUpperCase();",
    "description": "Checks if a string is upper case.\n\n- Convert the given string to upper case, using `String.prototype.toUpperCase()` and compare it to the original.",
    "example": "isUpperCase('ABC'); // true\nisUpperCase('A3@$'); // true\nisUpperCase('aB4'); // false",
    "id": "isUpperCase",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const isValidJSON = str => {\n  try {\n    JSON.parse(str);\n    return true;\n  } catch (e) {\n    return false;\n  }\n};",
    "description": "Checks if the provided string is a valid JSON.\n\n- Use `JSON.parse()` and a `try... catch` block to check if the provided string is a valid JSON.",
    "example": "isValidJSON('{\"name\":\"Adam\",\"age\":20}'); // true\nisValidJSON('{\"name\":\"Adam\",age:\"20\"}'); // false\nisValidJSON(null); // true",
    "id": "isValidJSON",
    "tags": [
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const isWeekday = (d = new Date()) => d.getDay() % 6 !== 0;",
    "description": "Checks if the given date is a weekday.\n\n- Use `Date.prototype.getDay()` to check weekday by using a modulo operator (`%`).\n- Omit the argument, `d`, to use the current date as default.",
    "example": "isWeekday(); // true (if current date is 2019-07-19)",
    "id": "isWeekday",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isWeekend = (d = new Date()) => d.getDay() % 6 === 0;",
    "description": "Checks if the given date is a weekend.\n\n- Use `Date.prototype.getDay()` to check weekend by using a modulo operator (`%`).\n- Omit the argument, `d`, to use the current date as default.",
    "example": "isWeekend(); // 2018-10-19 (if current date is 2018-10-18)",
    "id": "isWeekend",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const isWritableStream = val =>\n  val !== null &&\n  typeof val === 'object' &&\n  typeof val.pipe === 'function' &&\n  typeof val._write === 'function' &&\n  typeof val._writableState === 'object';",
    "description": "Checks if the given argument is a writable stream.\n\n- Check if the value is different from `null`.\n- Use `typeof` to check if the value is of type `object` and the `pipe` property is of type `function`.\n- Additionally check if the `typeof` the `_write` and `_writableState` properties are `function` and `object` respectively.",
    "example": "const fs = require('fs');\n\nisWritableStream(fs.createWriteStream('test.txt')); // true",
    "id": "isWritableStream",
    "tags": [
      "node",
      "type",
      "intermediate"
    ]
  },
  {
    "code": "const join = (arr, separator = ',', end = separator) =>\n  arr.reduce(\n    (acc, val, i) =>\n      i === arr.length - 2\n        ? acc + val + end\n        : i === arr.length - 1\n          ? acc + val\n          : acc + val + separator,\n    ''\n  );",
    "description": "Joins all elements of an array into a string and returns this string.\nUses a separator and an end separator.\n\n- Use `Array.prototype.reduce()` to combine elements into a string.\n- Omit the second argument, `separator`, to use a default separator of `','`.\n- Omit the third argument, `end`, to use the same value as `separator` by default.",
    "example": "join(['pen', 'pineapple', 'apple', 'pen'],',','&'); // 'pen,pineapple,apple&pen'\njoin(['pen', 'pineapple', 'apple', 'pen'], ','); // 'pen,pineapple,apple,pen'\njoin(['pen', 'pineapple', 'apple', 'pen']); // 'pen,pineapple,apple,pen'",
    "id": "join",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const juxt = (...fns) => (...args) => [...fns].map(fn => [...args].map(fn));",
    "description": "Takes several functions as argument and returns a function that is the juxtaposition of those functions.\n\n- Use `Array.prototype.map()` to return a `fn` that can take a variable number of `args`.\n- When `fn` is called, return an array containing the result of applying each `fn` to the `args`.",
    "example": "juxt(\n  x => x + 1,\n  x => x - 1,\n  x => x * 10\n)(1, 2, 3); // [[2, 3, 4], [0, 1, 2], [10, 20, 30]]\njuxt(\n  s => s.length,\n  s => s.split(' ').join('-')\n)('30 seconds of code'); // [[18], ['30-seconds-of-code']]",
    "id": "juxt",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const kMeans = (data, k = 1) => {\n  const centroids = data.slice(0, k);\n  const distances = Array.from({ length: data.length }, () =>\n    Array.from({ length: k }, () => 0)\n  );\n  const classes = Array.from({ length: data.length }, () => -1);\n  let itr = true;\n\n  while (itr) {\n    itr = false;\n\n    for (let d in data) {\n      for (let c = 0; c < k; c++) {\n        distances[d][c] = Math.hypot(\n          ...Object.keys(data[0]).map(key => data[d][key] - centroids[c][key])\n        );\n      }\n      const m = distances[d].indexOf(Math.min(...distances[d]));\n      if (classes[d] !== m) itr = true;\n      classes[d] = m;\n    }\n\n    for (let c = 0; c < k; c++) {\n      centroids[c] = Array.from({ length: data[0].length }, () => 0);\n      const size = data.reduce((acc, _, d) => {\n        if (classes[d] === c) {\n          acc++;\n          for (let i in data[0]) centroids[c][i] += data[d][i];\n        }\n        return acc;\n      }, 0);\n      for (let i in data[0]) {\n        centroids[c][i] = parseFloat(Number(centroids[c][i] / size).toFixed(2));\n      }\n    }\n  }\n\n  return classes;\n};",
    "description": "Groups the given data into `k` clusters, using the [k-means clustering](https://en.wikipedia.org/wiki/K-means_clustering) algorithm.\n\n- Use `Array.from()` and `Array.prototype.slice()` to initialize appropriate variables for the cluster `centroids`, `distances` and `classes`.\n- Use a `while` loop to repeat the assignment and update steps as long as there are changes in the previous iteration, as indicated by `itr`.\n- Calculate the euclidean distance between each data point and centroid using `Math.hypot()`, `Object.keys()` and `Array.prototype.map()`.\n- Use `Array.prototype.indexOf()` and `Math.min()` to find the closest centroid.\n- Use `Array.from()` and `Array.prototype.reduce()`, as well as `parseFloat()` and `Number.prototype.toFixed()` to calculate the new centroids.",
    "example": "kMeans([[0, 0], [0, 1], [1, 3], [2, 0]], 2); // [0, 1, 1, 0]",
    "id": "kMeans",
    "tags": [
      "algorithm",
      "array",
      "advanced"
    ]
  },
  {
    "code": "const kNearestNeighbors = (data, labels, point, k = 3) => {\n  const kNearest = data\n    .map((el, i) => ({\n      dist: Math.hypot(...Object.keys(el).map(key => point[key] - el[key])),\n      label: labels[i]\n    }))\n    .sort((a, b) => a.dist - b.dist)\n    .slice(0, k);\n\n  return kNearest.reduce(\n    (acc, { label }, i) => {\n      acc.classCounts[label] =\n        Object.keys(acc.classCounts).indexOf(label) !== -1\n          ? acc.classCounts[label] + 1\n          : 1;\n      if (acc.classCounts[label] > acc.topClassCount) {\n        acc.topClassCount = acc.classCounts[label];\n        acc.topClass = label;\n      }\n      return acc;\n    },\n    {\n      classCounts: {},\n      topClass: kNearest[0].label,\n      topClassCount: 0\n    }\n  ).topClass;\n};",
    "description": "Classifies a data point relative to a labelled data set, using the [k-nearest neighbors](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm) algorithm.\n\n- Use `Array.prototype.map()` to map the `data` to objects. Each object contains the euclidean distance of the element from `point`, calculated using `Math.hypot()`, `Object.keys()` and its `label`.\n- Use `Array.prototype.sort()` and `Array.prototype.slice()` to get the `k` nearest neighbors of `point`.\n- Use `Array.prototype.reduce()` in combination with `Object.keys()` and `Array.prototype.indexOf()` to find the most frequent `label` among them.",
    "example": "const data = [[0, 0], [0, 1], [1, 3], [2, 0]];\nconst labels = [0, 1, 1, 0];\n\nkNearestNeighbors(data, labels, [1, 2], 2); // 1\nkNearestNeighbors(data, labels, [1, 0], 2); // 0",
    "id": "kNearestNeighbors",
    "tags": [
      "algorithm",
      "array",
      "advanced"
    ]
  },
  {
    "code": "const kmToMiles = km => km * 0.621371;",
    "description": "Converts kilometers to miles.\n\n- Follow the conversion formula `mi = km * 0.621371`.",
    "example": "kmToMiles(8.1) // 5.0331051",
    "id": "kmToMiles",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const last = arr => (arr && arr.length ? arr[arr.length - 1] : undefined);",
    "description": "Returns the last element in an array.\n\n- Check if `arr` is truthy and has a `length` property.\n- Use `Array.prototype.length - 1` to compute the index of the last element of the given array and return it, otherwise return `undefined`.",
    "example": "last([1, 2, 3]); // 3\nlast([]); // undefined\nlast(null); // undefined\nlast(undefined); // undefined",
    "id": "last",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const lastDateOfMonth = (date = new Date()) => {\n  let d = new Date(date.getFullYear(), date.getMonth() + 1, 0);\n  return d.toISOString().split('T')[0];\n};",
    "description": "Returns the string representation of the last date in the given date's month.\n\n- Use `Date.prototype.getFullYear()`, `Date.prototype.getMonth()` to get the current year and month from the given date.\n- Use the `new Date()` constructor to create a new date with the given year and month incremented by `1`, and the day set to `0` (last day of previous month).\n- Omit the argument, `date`, to use the current date by default.",
    "example": "lastDateOfMonth(new Date('2015-08-11')); // '2015-08-30'",
    "id": "lastDateOfMonth",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const lcm = (...arr) => {\n  const gcd = (x, y) => (!y ? x : gcd(y, x % y));\n  const _lcm = (x, y) => (x * y) / gcd(x, y);\n  return [...arr].reduce((a, b) => _lcm(a, b));\n};",
    "description": "Calculates the least common multiple of two or more numbers.\n\n- Use the greatest common divisor (GCD) formula and the fact that `lcm(x, y) = x * y / gcd(x, y)` to determine the least common multiple.\n- The GCD formula uses recursion.",
    "example": "lcm(12, 7); // 84\nlcm(...[1, 3, 4, 5]); // 60",
    "id": "lcm",
    "tags": [
      "math",
      "algorithm",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const levenshteinDistance = (s, t) => {\n  if (!s.length) return t.length;\n  if (!t.length) return s.length;\n  const arr = [];\n  for (let i = 0; i <= t.length; i++) {\n    arr[i] = [i];\n    for (let j = 1; j <= s.length; j++) {\n      arr[i][j] =\n        i === 0\n          ? j\n          : Math.min(\n              arr[i - 1][j] + 1,\n              arr[i][j - 1] + 1,\n              arr[i - 1][j - 1] + (s[j - 1] === t[i - 1] ? 0 : 1)\n            );\n    }\n  }\n  return arr[t.length][s.length];\n};",
    "description": "Calculates the difference between two strings, using the [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance) algorithm.\n\n- If either of the two strings has a `length` of zero, return the `length` of the other one.\n- Use a `for` loop to iterate over the letters of the target string and a nested `for` loop to iterate over the letters of the source string.\n- Calculate the cost of substituting the letters corresponding to `i - 1` and `j - 1` in the target and source respectively (`0` if they are the same, `1` otherwise).\n- Use `Math.min()` to populate each element in the 2D array with the minimum of the cell above incremented by one, the cell to the left incremented by one or the cell to the top left incremented by the previously calculated cost.\n- Return the last element of the last row of the produced array.",
    "example": "levenshteinDistance('duck', 'dark'); // 2",
    "id": "levenshteinDistance",
    "tags": [
      "string",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const linearSearch = (arr, item) => {\n  for (const i in arr) {\n    if (arr[i] === item) return +i;\n  }\n  return -1;\n};",
    "description": "Finds the first index of a given element in an array using the linear search algorithm.\n\n- Use a `for...in` loop to iterate over the indexes of the given array.\n- Check if the element in the corresponding index is equal to `item`.\n- If the element is found, return the index, using the unary `+` operator to convert it from a string to a number.\n- If the element is not found after iterating over the whole array, return `-1`.",
    "example": "linearSearch([2, 9, 9], 9); // 1\nlinearSearch([2, 9, 9], 7); // -1",
    "id": "linearSearch",
    "tags": [
      "algorithm",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const listenOnce = (el, evt, fn) =>\n  el.addEventListener(evt, fn, { once: true });",
    "description": "Adds an event listener to an element that will only run the callback the first time the event is triggered.\n\n- Use `EventTarget.addEventListener()` to add an event listener to an element.\n- Use `{ once: true }` as options to only run the given callback once.",
    "example": "listenOnce(\n  document.getElementById('my-id'),\n  'click',\n  () => console.log('Hello world')\n); // 'Hello world' will only be logged on the first click",
    "id": "listenOnce",
    "tags": [
      "browser",
      "event",
      "beginner"
    ]
  },
  {
    "code": "const logBase = (n, base) => Math.log(n) / Math.log(base);",
    "description": "Calculates the logarithm of the given number in the given base.\n\n- Use `Math.log()` to get the logarithm from the value and the base and divide them.",
    "example": "logBase(10, 10); // 1\nlogBase(100, 10); // 2",
    "id": "logBase",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const longestItem = (...vals) =>\n  vals.reduce((a, x) => (x.length > a.length ? x : a));",
    "description": "Takes any number of iterable objects or objects with a `length` property and returns the longest one.\n\n- Use `Array.prototype.reduce()`, comparing the length of objects to find the longest one.\n- If multiple objects have the same length, the first one will be returned.\n- Returns `undefined` if no arguments are provided.",
    "example": "longestItem('this', 'is', 'a', 'testcase'); // 'testcase'\nlongestItem(...['a', 'ab', 'abc']); // 'abc'\nlongestItem(...['a', 'ab', 'abc'], 'abcd'); // 'abcd'\nlongestItem([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]); // [1, 2, 3, 4, 5]\nlongestItem([1, 2, 3], 'foobar'); // 'foobar'",
    "id": "longestItem",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const lowercaseKeys = obj =>\n  Object.keys(obj).reduce((acc, key) => {\n    acc[key.toLowerCase()] = obj[key];\n    return acc;\n  }, {});",
    "description": "Creates a new object from the specified object, where all the keys are in lowercase.\n\n- Use `Object.keys()` and `Array.prototype.reduce()` to create a new object from the specified object.\n- Convert each key in the original object to lowercase, using `String.prototype.toLowerCase()`.",
    "example": "const myObj = { Name: 'Adam', sUrnAME: 'Smith' };\nconst myObjLower = lowercaseKeys(myObj); // {name: 'Adam', surname: 'Smith'};",
    "id": "lowercaseKeys",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const luhnCheck = num => {\n  let arr = (num + '')\n    .split('')\n    .reverse()\n    .map(x => parseInt(x));\n  let lastDigit = arr.splice(0, 1)[0];\n  let sum = arr.reduce(\n    (acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val *= 2) > 9 ? val - 9 : val)),\n    0\n  );\n  sum += lastDigit;\n  return sum % 10 === 0;\n};",
    "description": "Implements the [Luhn Algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers, National Provider Identifier numbers etc.\n\n- Use `String.prototype.split('')`, `Array.prototype.reverse()` and `Array.prototype.map()` in combination with `parseInt()` to obtain an array of digits.\n- Use `Array.prototype.splice(0, 1)` to obtain the last digit.\n- Use `Array.prototype.reduce()` to implement the Luhn Algorithm.\n- Return `true` if `sum` is divisible by `10`, `false` otherwise.",
    "example": "luhnCheck('4485275742308327'); // true\nluhnCheck(6011329933655299); //  true\nluhnCheck(123456789); // false",
    "id": "luhnCheck",
    "tags": [
      "math",
      "algorithm",
      "advanced"
    ]
  },
  {
    "code": "const mapConsecutive = (arr, n, fn) =>\n  arr.slice(n - 1).map((v, i) => fn(arr.slice(i, i + n)));",
    "description": "Maps each block of `n` consencutive elements using the given function, `fn`.\n\n- Use `Array.prototype.slice()` to get `arr` with `n` elements removed from the left.\n- Use `Array.prototype.map()` and `Array.prototype.slice()` to apply `fn` to each block of `n` consecutive elements in `arr`.",
    "example": "mapConsecutive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, x => x.join('-'));\n// ['1-2-3', '2-3-4', '3-4-5', '4-5-6', '5-6-7', '6-7-8', '7-8-9', '8-9-10'];",
    "id": "mapConsecutive",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const mapKeys = (obj, fn) =>\n  Object.keys(obj).reduce((acc, k) => {\n    acc[fn(obj[k], k, obj)] = obj[k];\n    return acc;\n  }, {});",
    "description": "Maps the keys of an object using the provided function, generating a new object.\n\n- Use `Object.keys()` to iterate over the object's keys.\n- Use `Array.prototype.reduce()` to create a new object with the same values and mapped keys using `fn`.",
    "example": "mapKeys({ a: 1, b: 2 }, (val, key) => key + val); // { a1: 1, b2: 2 }",
    "id": "mapKeys",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const mapNumRange = (num, inMin, inMax, outMin, outMax) =>\n  ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;",
    "description": "Maps a number from one range to another range.\n\n- Return `num` mapped between `outMin`-`outMax` from `inMin`-`inMax`.",
    "example": "mapNumRange(5, 0, 10, 0, 100); // 50",
    "id": "mapNumRange",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const mapObject = (arr, fn) =>\n  arr.reduce((acc, el, i) => {\n    acc[el] = fn(el, i, arr);\n    return acc;\n  }, {});",
    "description": "Maps the values of an array to an object using a function.\n\n- Use `Array.prototype.reduce()` to apply `fn` to each element in `arr` and combine the results into an object.\n- Use `el` as the key for each property and the result of `fn` as the value.",
    "example": "mapObject([1, 2, 3], a => a * a); // { 1: 1, 2: 4, 3: 9 }",
    "id": "mapObject",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const mapString = (str, fn) =>\n  str\n    .split('')\n    .map((c, i) => fn(c, i, str))\n    .join('');",
    "description": "Creates a new string with the results of calling a provided function on every character in the given string.\n\n- Use `String.prototype.split('')` and `Array.prototype.map()` to call the provided function, `fn`, for each character in `str`.\n- Use `Array.prototype.join('')` to recombine the array of characters into a string.\n- The callback function, `fn`, takes three arguments (the current character, the index of the current character and the string `mapString` was called upon).",
    "example": "mapString('lorem ipsum', c => c.toUpperCase()); // 'LOREM IPSUM'",
    "id": "mapString",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const mapValues = (obj, fn) =>\n  Object.keys(obj).reduce((acc, k) => {\n    acc[k] = fn(obj[k], k, obj);\n    return acc;\n  }, {});",
    "description": "Maps the values of an object using the provided function, generating a new object with the same keys.\n\n- Use `Object.keys()` to iterate over the object's keys.\n- Use `Array.prototype.reduce()` to create a new object with the same keys and mapped values using `fn`.",
    "example": "const users = {\n  fred: { user: 'fred', age: 40 },\n  pebbles: { user: 'pebbles', age: 1 }\n};\nmapValues(users, u => u.age); // { fred: 40, pebbles: 1 }",
    "id": "mapValues",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const mask = (cc, num = 4, mask = '*') =>\n  \\`\\${cc}\\`.slice(-num).padStart(\\`\\${cc}\\`.length, mask);",
    "description": "Replaces all but the last `num` of characters with the specified mask character.\n\n- Use `String.prototype.slice()` to grab the portion of the characters that will remain unmasked.\n- Use `String.padStart()` to fill the beginning of the string with the `mask` character up to the original length.\n- If `num` is negative, the unmasked characters will be at the start of the string.\n- Omit the second argument, `num`, to keep a default of `4` characters unmasked.\n- Omit the third argument, `mask`, to use a default character of `'*'` for the mask.",
    "example": "mask(1234567890); // '******7890'\nmask(1234567890, 3); // '*******890'\nmask(1234567890, -4, '$'); // '$$$$567890'",
    "id": "mask",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const matches = (obj, source) =>\n  Object.keys(source).every(\n    key => obj.hasOwnProperty(key) && obj[key] === source[key]\n  );",
    "description": "Compares two objects to determine if the first one contains equivalent property values to the second one.\n\n- Use `Object.keys()` to get all the keys of the second object.\n- Use `Array.prototype.every()`, `Object.prototype.hasOwnProperty()` and strict comparison to determine if all keys exist in the first object and have the same values.",
    "example": "matches({ age: 25, hair: 'long', beard: true }, { hair: 'long', beard: true });\n// true\nmatches({ hair: 'long', beard: true }, { age: 25, hair: 'long', beard: true });\n// false",
    "id": "matches",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const matchesWith = (obj, source, fn) =>\n  Object.keys(source).every(key =>\n    obj.hasOwnProperty(key) && fn\n      ? fn(obj[key], source[key], key, obj, source)\n      : obj[key] == source[key]\n  );",
    "description": "Compares two objects to determine if the first one contains equivalent property values to the second one, based on a provided function.\n\n- Use `Object.keys()` to get all the keys of the second object.\n- Use `Array.prototype.every()`, `Object.prototype.hasOwnProperty()` and the provided function to determine if all keys exist in the first object and have equivalent values.\n- If no function is provided, the values will be compared using the equality operator.",
    "example": "const isGreeting = val => /^h(?:i|ello)$/.test(val);\nmatchesWith(\n  { greeting: 'hello' },\n  { greeting: 'hi' },\n  (oV, sV) => isGreeting(oV) && isGreeting(sV)\n); // true",
    "id": "matchesWith",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const maxBy = (arr, fn) =>\n  Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));",
    "description": "Returns the maximum value of an array, after mapping each element to a value using the provided function.\n\n- Use `Array.prototype.map()` to map each element to the value returned by `fn`.\n- Use `Math.max()` to get the maximum value.",
    "example": "maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], x => x.n); // 8\nmaxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 8",
    "id": "maxBy",
    "tags": [
      "math",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const maxDate = (...dates) => new Date(Math.max(...dates));",
    "description": "Returns the maximum of the given dates.\n\n- Use the ES6 spread syntax with `Math.max()` to find the maximum date value.\n- Use `new Date()` to convert it to a `Date` object.",
    "example": "const dates = [\n  new Date(2017, 4, 13),\n  new Date(2018, 2, 12),\n  new Date(2016, 0, 10),\n  new Date(2016, 0, 9)\n];\nmaxDate(...dates); // 2018-03-11T22:00:00.000Z",
    "id": "maxDate",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);",
    "description": "Returns the `n` maximum elements from the provided array.\n\n- Use `Array.prototype.sort()` combined with the spread operator (`...`) to create a shallow clone of the array and sort it in descending order.\n- Use `Array.prototype.slice()` to get the specified number of elements.\n- Omit the second argument, `n`, to get a one-element array.\n- If `n` is greater than or equal to the provided array's length, then return the original array (sorted in descending order).",
    "example": "maxN([1, 2, 3]); // [3]\nmaxN([1, 2, 3], 2); // [3, 2]",
    "id": "maxN",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const median = arr => {\n  const mid = Math.floor(arr.length / 2),\n    nums = [...arr].sort((a, b) => a - b);\n  return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;\n};",
    "description": "Calculates the median of an array of numbers.\n\n- Find the middle of the array, use `Array.prototype.sort()` to sort the values.\n- Return the number at the midpoint if `Array.prototype.length` is odd, otherwise the average of the two middle numbers.",
    "example": "median([5, 6, 50, 1, -5]); // 5",
    "id": "median",
    "tags": [
      "math",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const memoize = fn => {\n  const cache = new Map();\n  const cached = function (val) {\n    return cache.has(val)\n      ? cache.get(val)\n      : cache.set(val, fn.call(this, val)) && cache.get(val);\n  };\n  cached.cache = cache;\n  return cached;\n};",
    "description": "Returns the memoized (cached) function.\n\n- Create an empty cache by instantiating a new `Map` object.\n- Return a function which takes a single argument to be supplied to the memoized function by first checking if the function's output for that specific input value is already cached, or store and return it if not.\n- The `function` keyword must be used in order to allow the memoized function to have its `this` context changed if necessary.\n- Allow access to the `cache` by setting it as a property on the returned function.",
    "example": "// See the `anagrams` snippet.\nconst anagramsCached = memoize(anagrams);\nanagramsCached('javascript'); // takes a long time\nanagramsCached('javascript'); // returns virtually instantly since it's cached\nconsole.log(anagramsCached.cache); // The cached anagrams map",
    "id": "memoize",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const merge = (...objs) =>\n  [...objs].reduce(\n    (acc, obj) =>\n      Object.keys(obj).reduce((a, k) => {\n        acc[k] = acc.hasOwnProperty(k)\n          ? [].concat(acc[k]).concat(obj[k])\n          : obj[k];\n        return acc;\n      }, {}),\n    {}\n  );",
    "description": "Creates a new object from the combination of two or more objects.\n\n- Use `Array.prototype.reduce()` combined with `Object.keys()` to iterate over all objects and keys.\n- Use `Object.prototype.hasOwnProperty()` and `Array.prototype.concat()` to append values for keys existing in multiple objects.",
    "example": "const object = {\n  a: [{ x: 2 }, { y: 4 }],\n  b: 1\n};\nconst other = {\n  a: { z: 3 },\n  b: [2, 3],\n  c: 'foo'\n};\nmerge(object, other);\n// { a: [ { x: 2 }, { y: 4 }, { z: 3 } ], b: [ 1, 2, 3 ], c: 'foo' }",
    "id": "merge",
    "tags": [
      "object",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const mergeSort = arr => {\n  if (arr.length < 2) return arr;\n  const mid = Math.floor(arr.length / 2);\n  const l = mergeSort(arr.slice(0, mid));\n  const r = mergeSort(arr.slice(mid, arr.length));\n  return Array.from({ length: l.length + r.length }, () => {\n    if (!l.length) return r.shift();\n    else if (!r.length) return l.shift();\n    else return l[0] > r[0] ? r.shift() : l.shift();\n  });\n};",
    "description": "Sorts an array of numbers, using the merge sort algorithm.\n\n- Use recursion.\n- If the `length` of the array is less than `2`, return the array.\n- Use `Math.floor()` to calculate the middle point of the array.\n- Use `Array.prototype.slice()` to slice the array in two and recursively call `mergeSort()` on the created subarrays.\n- Finally, use `Array.from()` and `Array.prototype.shift()` to combine the two sorted subarrays into one.",
    "example": "mergeSort([5, 1, 4, 2, 3]); // [1, 2, 3, 4, 5]",
    "id": "mergeSort",
    "tags": [
      "algorithm",
      "array",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const mergeSortedArrays = (a, b) => {\n  const _a = [...a],\n    _b = [...b];\n  return Array.from({ length: _a.length + _b.length }, () => {\n    if (!_a.length) return _b.shift();\n    else if (!_b.length) return _a.shift();\n    else return _a[0] > _b[0] ? _b.shift() : _a.shift();\n  });\n};",
    "description": "Merges two sorted arrays into one.\n\n- Use the spread operator (`...`) to clone both of the given arrays.\n- Use `Array.from()` to create an array of the appropriate length based on the given arrays.\n- Use `Array.prototype.shift()` to populate the newly created array from the removed elements of the cloned arrays.",
    "example": "mergeSortedArrays([1, 4, 5], [2, 3, 6]); // [1, 2, 3, 4, 5, 6]",
    "id": "mergeSortedArrays",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2];",
    "description": "Calculates the midpoint between two pairs of (x,y) points.\n\n- Destructure the array to get `x1`, `y1`, `x2` and `y2`.\n- Calculate the midpoint for each dimension by dividing the sum of the two endpoints by `2`.",
    "example": "midpoint([2, 2], [4, 4]); // [3, 3]\nmidpoint([4, 4], [6, 6]); // [5, 5]\nmidpoint([1, 3], [2, 4]); // [1.5, 3.5]",
    "id": "midpoint",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const milesToKm = miles => miles * 1.609344;",
    "description": "Converts miles to kilometers.\n\n- Follow the conversion formula `km = mi * 1.609344`.",
    "example": "milesToKm(5); // ~8.04672",
    "id": "milesToKm",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const minBy = (arr, fn) =>\n  Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));",
    "description": "Returns the minimum value of an array, after mapping each element to a value using the provided function.\n\n- Use `Array.prototype.map()` to map each element to the value returned by `fn`.\n- Use `Math.min()` to get the minimum value.",
    "example": "minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], x => x.n); // 2\nminBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 2",
    "id": "minBy",
    "tags": [
      "math",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const minDate = (...dates) => new Date(Math.min(...dates));",
    "description": "Returns the minimum of the given dates.\n\n- Use the ES6 spread syntax with `Math.min()` to find the minimum date value.\n- Use `new Date()` to convert it to a `Date` object.",
    "example": "const dates = [\n  new Date(2017, 4, 13),\n  new Date(2018, 2, 12),\n  new Date(2016, 0, 10),\n  new Date(2016, 0, 9)\n];\nminDate(...dates); // 2016-01-08T22:00:00.000Z",
    "id": "minDate",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);",
    "description": "Returns the `n` minimum elements from the provided array.\n\n- Use `Array.prototype.sort()` combined with the spread operator (`...`) to create a shallow clone of the array and sort it in ascending order.\n- Use `Array.prototype.slice()` to get the specified number of elements.\n- Omit the second argument, `n`, to get a one-element array.\n- If `n` is greater than or equal to the provided array's length, then return the original array (sorted in ascending order).",
    "example": "minN([1, 2, 3]); // [1]\nminN([1, 2, 3], 2); // [1, 2]",
    "id": "minN",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const mostFrequent = arr =>\n  Object.entries(\n    arr.reduce((a, v) => {\n      a[v] = a[v] ? a[v] + 1 : 1;\n      return a;\n    }, {})\n  ).reduce((a, v) => (v[1] >= a[1] ? v : a), [null, 0])[0];",
    "description": "Returns the most frequent element in an array.\n\n- Use `Array.prototype.reduce()` to map unique values to an object's keys, adding to existing keys every time the same value is encountered.\n- Use `Object.entries()` on the result in combination with `Array.prototype.reduce()` to get the most frequent value in the array.",
    "example": "mostFrequent(['a', 'b', 'a', 'c', 'a', 'a', 'b']); // 'a'",
    "id": "mostFrequent",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const mostPerformant = (fns, iterations = 10000) => {\n  const times = fns.map(fn => {\n    const before = performance.now();\n    for (let i = 0; i < iterations; i++) fn();\n    return performance.now() - before;\n  });\n  return times.indexOf(Math.min(...times));\n};",
    "description": "Returns the index of the function in an array of functions which executed the fastest.\n\n- Use `Array.prototype.map()` to generate an array where each value is the total time taken to execute the function after `iterations` times.\n- Use the difference in `performance.now()` values before and after to get the total time in milliseconds to a high degree of accuracy.\n- Use `Math.min()` to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function.\n- Omit the second argument, `iterations`, to use a default of `10000` iterations.\n- The more iterations, the more reliable the result but the longer it will take.",
    "example": "mostPerformant([\n  () => {\n    // Loops through the entire array before returning `false`\n    [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number');\n  },\n  () => {\n    // Only needs to reach index `1` before returning `false`\n    [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number');\n  }\n]); // 1",
    "id": "mostPerformant",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const negate = func => (...args) => !func(...args);",
    "description": "Negates a predicate function.\n\n- Take a predicate function and apply the not operator (`!`) to it with its arguments.",
    "example": "[1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ]",
    "id": "negate",
    "tags": [
      "function",
      "beginner"
    ]
  },
  {
    "code": "const nest = (items, id = null, link = 'parent_id') =>\n  items\n    .filter(item => item[link] === id)\n    .map(item => ({ ...item, children: nest(items, item.id, link) }));",
    "description": "Nests recursively objects linked to one another in a flat array.\n\n- Use recursion.\n- Use `Array.prototype.filter()` to filter the items where the `id` matches the `link`.\n- Use `Array.prototype.map()` to map each item to a new object that has a `children` property which recursively nests the items based on which ones are children of the current item.\n- Omit the second argument, `id`, to default to `null` which indicates the object is not linked to another one (i.e. it is a top level object).\n- Omit the third argument, `link`, to use `'parent_id'` as the default property which links the object to another one by its `id`.",
    "example": "const comments = [\n  { id: 1, parent_id: null },\n  { id: 2, parent_id: 1 },\n  { id: 3, parent_id: 1 },\n  { id: 4, parent_id: 2 },\n  { id: 5, parent_id: 4 }\n];\nconst nestedComments = nest(comments);\n// [{ id: 1, parent_id: null, children: [...] }]",
    "id": "nest",
    "tags": [
      "object",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const nodeListToArray = nodeList => [...nodeList];",
    "description": "Converts a `NodeList` to an array.\n\n- Use spread operator (`...`) inside new array to convert a `NodeList` to an array.",
    "example": "nodeListToArray(document.childNodes); // [ <!DOCTYPE html>, html ]",
    "id": "nodeListToArray",
    "tags": [
      "browser",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const none = (arr, fn = Boolean) => !arr.some(fn);",
    "description": "Checks if the provided predicate function returns `false` for all elements in a collection.\n\n- Use `Array.prototype.some()` to test if any elements in the collection return `true` based on `fn`.\n- Omit the second argument, `fn`, to use `Boolean` as a default.",
    "example": "none([0, 1, 3, 0], x => x == 2); // true\nnone([0, 0, 0]); // true",
    "id": "none",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const nor = (a, b) => !(a||b);",
    "description": "Checks if none of the arguments are `true`.\n\n- Use the logical not (`!`) operator to return the inverse of the logical or (`||`) of the two given values.",
    "example": "nor(true, true); // false\nnor(true, false); // false\nnor(false, false); // true",
    "id": "nor",
    "tags": [
      "math",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const normalizeLineEndings = (str, normalized = '\\r\\n') =>\n  str.replace(/\\r?\\n/g, normalized);",
    "description": "Normalizes line endings in a string.\n\n- Use `String.prototype.replace()` and a regular expression to match and replace line endings with the `normalized` version.\n- Omit the second argument, `normalized`, to use the default value of `'\\r\\n'`.",
    "example": "normalizeLineEndings('This\\r\\nis a\\nmultiline\\nstring.\\r\\n');\n// 'This\\r\\nis a\\r\\nmultiline\\r\\nstring.\\r\\n'\nnormalizeLineEndings('This\\r\\nis a\\nmultiline\\nstring.\\r\\n', '\\n');\n// 'This\\nis a\\nmultiline\\nstring.\\n'",
    "id": "normalizeLineEndings",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const not = a => !a;",
    "description": "Returns the logical inverse of the given value.\n\n- Use the logical not (`!`) operator to return the inverse of the given value.",
    "example": "not(true); // false\nnot(false); // true",
    "id": "not",
    "tags": [
      "math",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const nthArg = n => (...args) => args.slice(n)[0];",
    "description": "Creates a function that gets the argument at index `n`.\n\n- Use `Array.prototype.slice()` to get the desired argument at index `n`.\n- If `n` is negative, the nth argument from the end is returned.",
    "example": "const third = nthArg(2);\nthird(1, 2, 3); // 3\nthird(1, 2); // undefined\nconst last = nthArg(-1);\nlast(1, 2, 3, 4, 5); // 5",
    "id": "nthArg",
    "tags": [
      "function",
      "beginner"
    ]
  },
  {
    "code": "const nthElement = (arr, n = 0) =>\n  (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];",
    "description": "Returns the nth element of an array.\n\n- Use `Array.prototype.slice()` to get an array containing the nth element at the first place.\n- If the index is out of bounds, return `undefined`.\n- Omit the second argument, `n`, to get the first element of the array.",
    "example": "nthElement(['a', 'b', 'c'], 1); // 'b'\nnthElement(['a', 'b', 'b'], -3); // 'a'",
    "id": "nthElement",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const nthRoot = (x, n) => Math.pow(x, 1 / n);",
    "description": "Calculates the nth root of a given number.\n\n- Use `Math.pow()` to calculate `x` to the power of `1/n` which is equal to the nth root of `x`.",
    "example": "nthRoot(32, 5); // 2",
    "id": "nthRoot",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const objectFromPairs = arr =>\n  arr.reduce((a, [key, val]) => ((a[key] = val), a), {});",
    "description": "Creates an object from the given key-value pairs.\n\n- Use `Array.prototype.reduce()` to create and combine key-value pairs.",
    "example": "objectFromPairs([['a', 1], ['b', 2]]); // {a: 1, b: 2}",
    "id": "objectFromPairs",
    "tags": [
      "object",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const objectToEntries = obj => Object.keys(obj).map(k => [k, obj[k]]);",
    "description": "Creates an array of key-value pair arrays from an object.\n\n- Use `Object.keys()` and `Array.prototype.map()` to iterate over the object's keys and produce an array with key-value pairs.",
    "example": "objectToEntries({ a: 1, b: 2 }); // [ ['a', 1], ['b', 2] ]",
    "id": "objectToEntries",
    "tags": [
      "object",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const objectToPairs = obj => Object.entries(obj);",
    "description": "Creates an array of key-value pair arrays from an object.\n\n- Use `Object.entries()` to get an array of key-value pair arrays from the given object.",
    "example": "objectToPairs({ a: 1, b: 2 }); // [ ['a', 1], ['b', 2] ]",
    "id": "objectToPairs",
    "tags": [
      "object",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const objectToQueryString = queryParameters => {\n  return queryParameters\n    ? Object.entries(queryParameters).reduce(\n        (queryString, [key, val], index) => {\n          const symbol = queryString.length === 0 ? '?' : '&';\n          queryString +=\n            typeof val === 'string' ? \\`\\${symbol}\\${key}=\\${val}\\` : '';\n          return queryString;\n        },\n        ''\n      )\n    : '';\n};",
    "description": "Generates a query string from the key-value pairs of the given object.\n\n- Use `Array.prototype.reduce()` on `Object.entries(queryParameters)` to create the query string.\n- Determine the `symbol` to be either `?` or `&` based on the length of `queryString`.\n- Concatenate `val` to `queryString` only if it's a string.\n- Return the `queryString` or an empty string when the `queryParameters` are falsy.",
    "example": "objectToQueryString({ page: '1', size: '2kg', key: undefined });\n// '?page=1&size=2kg'",
    "id": "objectToQueryString",
    "tags": [
      "object",
      "advanced"
    ]
  },
  {
    "code": "const observeMutations = (element, callback, options) => {\n  const observer = new MutationObserver(mutations =>\n    mutations.forEach(m => callback(m))\n  );\n  observer.observe(\n    element,\n    Object.assign(\n      {\n        childList: true,\n        attributes: true,\n        attributeOldValue: true,\n        characterData: true,\n        characterDataOldValue: true,\n        subtree: true,\n      },\n      options\n    )\n  );\n  return observer;\n};",
    "description": "Creates a new `MutationObserver` and runs the provided callback for each mutation on the specified element.\n\n- Use a [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) to observe mutations on the given element.\n- Use `Array.prototype.forEach()` to run the callback for each mutation that is observed.\n- Omit the third argument, `options`, to use the default [options](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#MutationObserverInit) (all `true`).",
    "example": "const obs = observeMutations(document, console.log);\n// Logs all mutations that happen on the page\nobs.disconnect();\n// Disconnects the observer and stops logging mutations on the page",
    "id": "observeMutations",
    "tags": [
      "browser",
      "event",
      "advanced"
    ]
  },
  {
    "code": "const off = (el, evt, fn, opts = false) =>\n  el.removeEventListener(evt, fn, opts);",
    "description": "Removes an event listener from an element.\n\n- Use `EventTarget.removeEventListener()` to remove an event listener from an element.\n- Omit the fourth argument `opts` to use `false` or specify it based on the options used when the event listener was added.",
    "example": "const fn = () => console.log('!');\ndocument.body.addEventListener('click', fn);\noff(document.body, 'click', fn); // no longer logs '!' upon clicking on the page",
    "id": "off",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];",
    "description": "Moves the specified amount of elements to the end of the array.\n\n- Use `Array.prototype.slice()` twice to get the elements after the specified index and the elements before that.\n- Use the spread operator (`...`) to combine the two into one array.\n- If `offset` is negative, the elements will be moved from end to start.",
    "example": "offset([1, 2, 3, 4, 5], 2); // [3, 4, 5, 1, 2]\noffset([1, 2, 3, 4, 5], -2); // [4, 5, 1, 2, 3]",
    "id": "offset",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const omit = (obj, arr) =>\n  Object.keys(obj)\n    .filter(k => !arr.includes(k))\n    .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});",
    "description": "Omits the key-value pairs corresponding to the given keys from an object.\n\n- Use `Object.keys()`, `Array.prototype.filter()` and `Array.prototype.includes()` to remove the provided keys.\n- Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs.",
    "example": "omit({ a: 1, b: '2', c: 3 }, ['b']); // { 'a': 1, 'c': 3 }",
    "id": "omit",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const omitBy = (obj, fn) =>\n  Object.keys(obj)\n    .filter(k => !fn(obj[k], k))\n    .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});",
    "description": "Omits the key-value pairs corresponding to the keys of the object for which the given function returns falsy.\n\n- Use `Object.keys()` and `Array.prototype.filter()` to remove the keys for which `fn` returns a truthy value.\n- Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs.\n- The callback function is invoked with two arguments: (value, key).",
    "example": "omitBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { b: '2' }",
    "id": "omitBy",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const on = (el, evt, fn, opts = {}) => {\n  const delegatorFn = e =>\n    e.target.matches(opts.target) && fn.call(e.target, e);\n  el.addEventListener(\n    evt,\n    opts.target ? delegatorFn : fn,\n    opts.options || false\n  );\n  if (opts.target) return delegatorFn;\n};",
    "description": "Adds an event listener to an element with the ability to use event delegation.\n\n- Use `EventTarget.addEventListener()` to add an event listener to an element.\n- If there is a `target` property supplied to the options object, ensure the event target matches the target specified and then invoke the callback by supplying the correct `this` context.\n- Omit `opts` to default to non-delegation behavior and event bubbling.\n- Returns a reference to the custom delegator function, in order to be possible to use with [`off`](/js/s/off).",
    "example": "const fn = () => console.log('!');\non(document.body, 'click', fn); // logs '!' upon clicking the body\non(document.body, 'click', fn, { target: 'p' });\n// logs '!' upon clicking a `p` element child of the body\non(document.body, 'click', fn, { options: true });\n// use capturing instead of bubbling",
    "id": "on",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const onClickOutside = (element, callback) => {\n  document.addEventListener('click', e => {\n    if (!element.contains(e.target)) callback();\n  });\n};",
    "description": "Runs the callback whenever the user clicks outside of the specified element.\n\n- Use `EventTarget.addEventListener()` to listen for `'click'` events.\n- Use `Node.contains()` to check if `Event.target` is a descendant of `element` and run `callback` if not.",
    "example": "onClickOutside('#my-element', () => console.log('Hello'));\n// Will log 'Hello' whenever the user clicks outside of #my-element",
    "id": "onClickOutside",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const onScrollStop = callback => {\n  let isScrolling;\n  window.addEventListener(\n    'scroll',\n    e => {\n      clearTimeout(isScrolling);\n      isScrolling = setTimeout(() => {\n        callback();\n      }, 150);\n    },\n    false\n  );\n};",
    "description": "Runs the callback whenever the user has stopped scrolling.\n\n- Use `EventTarget.addEventListener()` to listen for the `'scroll'` event.\n- Use `setTimeout()` to wait `150` ms until calling the given `callback`.\n- Use `clearTimeout()` to clear the timeout if a new `'scroll'` event is fired in under `150` ms.",
    "example": "onScrollStop(() => {\n  console.log('The user has stopped scrolling');\n});",
    "id": "onScrollStop",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const onUserInputChange = callback => {\n  let type = 'mouse',\n    lastTime = 0;\n  const mousemoveHandler = () => {\n    const now = performance.now();\n    if (now - lastTime < 20)\n      (type = 'mouse'),\n        callback(type),\n        document.removeEventListener('mousemove', mousemoveHandler);\n    lastTime = now;\n  };\n  document.addEventListener('touchstart', () => {\n    if (type === 'touch') return;\n    (type = 'touch'),\n      callback(type),\n      document.addEventListener('mousemove', mousemoveHandler);\n  });\n};",
    "description": "Runs the callback whenever the user input type changes (`mouse` or `touch`).\n\n- Use two event listeners.\n- Assume `mouse` input initially and bind a `'touchstart'` event listener to the document.\n- On `'touchstart'`, add a `'mousemove'` event listener to listen for two consecutive `'mousemove'` events firing within 20ms, using `performance.now()`.\n- Run the callback with the input type as an argument in either of these situations.",
    "example": "onUserInputChange(type => {\n  console.log('The user is now using', type, 'as an input method.');\n});",
    "id": "onUserInputChange",
    "tags": [
      "browser",
      "event",
      "advanced"
    ]
  },
  {
    "code": "const once = fn => {\n  let called = false;\n  return function(...args) {\n    if (called) return;\n    called = true;\n    return fn.apply(this, args);\n  };\n};",
    "description": "Ensures a function is called only once.\n\n- Utilizing a closure, use a flag, `called`, and set it to `true` once the function is called for the first time, preventing it from being called again.\n- In order to allow the function to have its `this` context changed (such as in an event listener), the `function` keyword must be used, and the supplied function must have the context applied.\n- Allow the function to be supplied with an arbitrary number of arguments using the rest/spread (`...`) operator.",
    "example": "const startApp = function(event) {\n  console.log(this, event); // document.body, MouseEvent\n};\ndocument.body.addEventListener('click', once(startApp));\n// only runs `startApp` once upon click",
    "id": "once",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const or = (a, b) => a || b;",
    "description": "Checks if at least one of the arguments is `true`.\n\n- Use the logical or (`||`) operator on the two given values.",
    "example": "or(true, true); // true\nor(true, false); // true\nor(false, false); // false",
    "id": "or",
    "tags": [
      "math",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const orderBy = (arr, props, orders) =>\n  [...arr].sort((a, b) =>\n    props.reduce((acc, prop, i) => {\n      if (acc === 0) {\n        const [p1, p2] =\n          orders && orders[i] === 'desc'\n            ? [b[prop], a[prop]]\n            : [a[prop], b[prop]];\n        acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;\n      }\n      return acc;\n    }, 0)\n  );",
    "description": "Sorts an array of objects, ordered by properties and orders.\n\n- Uses `Array.prototype.sort()`, `Array.prototype.reduce()` on the `props` array with a default value of `0`.\n- Use array destructuring to swap the properties position depending on the order supplied.\n- If no `orders` array is supplied, sort by `'asc'` by default.",
    "example": "const users = [\n  { name: 'fred', age: 48 },\n  { name: 'barney', age: 36 },\n  { name: 'fred', age: 40 },\n];\norderBy(users, ['name', 'age'], ['asc', 'desc']);\n// [{name: 'barney', age: 36}, {name: 'fred', age: 48}, {name: 'fred', age: 40}]\norderBy(users, ['name', 'age']);\n// [{name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}]",
    "id": "orderBy",
    "tags": [
      "object",
      "array",
      "advanced"
    ]
  },
  {
    "code": "const orderWith = (arr, prop, order) => {\n  const orderValues = order.reduce((acc, v, i) => {\n    acc[v] = i;\n    return acc;\n  }, {});\n  return [...arr].sort((a, b) => {\n    if (orderValues[a[prop]] === undefined) return 1;\n    if (orderValues[b[prop]] === undefined) return -1;\n    return orderValues[a[prop]] - orderValues[b[prop]];\n  });\n};",
    "description": "Sorts an array of objects, ordered by a property, based on the array of orders provided.\n\n- Use `Array.prototype.reduce()` to create an object from the `order` array with the values as keys and their original index as the value.\n- Use `Array.prototype.sort()` to sort the given array, skipping elements for which `prop` is empty or not in the `order` array.",
    "example": "const users = [\n  { name: 'fred', language: 'Javascript' },\n  { name: 'barney', language: 'TypeScript' },\n  { name: 'frannie', language: 'Javascript' },\n  { name: 'anna', language: 'Java' },\n  { name: 'jimmy' },\n  { name: 'nicky', language: 'Python' },\n];\norderWith(users, 'language', ['Javascript', 'TypeScript', 'Java']);\n/* \n[\n  { name: 'fred', language: 'Javascript' },\n  { name: 'frannie', language: 'Javascript' },\n  { name: 'barney', language: 'TypeScript' },\n  { name: 'anna', language: 'Java' },\n  { name: 'jimmy' },\n  { name: 'nicky', language: 'Python' }\n]\n*/",
    "id": "orderWith",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));",
    "description": "Creates a function that invokes each provided function with the arguments it receives and returns the results.\n\n- Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments.",
    "example": "const minMax = over(Math.min, Math.max);\nminMax(1, 2, 3, 4, 5); // [1, 5]",
    "id": "over",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const overArgs = (fn, transforms) =>\n  (...args) => fn(...args.map((val, i) => transforms[i](val)));",
    "description": "Creates a function that invokes the provided function with its arguments transformed.\n\n- Use `Array.prototype.map()` to apply `transforms` to `args` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`.",
    "example": "const square = n => n * n;\nconst double = n => n * 2;\nconst fn = overArgs((x, y) => [x, y], [square, double]);\nfn(9, 3); // [81, 6]",
    "id": "overArgs",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const pad = (str, length, char = ' ') =>\n  str.padStart((str.length + length) / 2, char).padEnd(length, char);",
    "description": "Pads a string on both sides with the specified character, if it's shorter than the specified `length`.\n\n- Use `String.prototype.padStart()` and `String.prototype.padEnd()` to pad both sides of the given string.\n- Omit the third argument, `char`, to use the whitespace character as the default padding character.",
    "example": "pad('cat', 8); // '  cat   '\npad(String(42), 6, '0'); // '004200'\npad('foobar', 3); // 'foobar'",
    "id": "pad",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const padNumber = (n, l) => \\`\\${n}\\`.padStart(l, '0');",
    "description": "Pads a given number to the specified length.\n\n- Use `String.prototype.padStart()` to pad the number to specified length, after converting it to a string.",
    "example": "padNumber(1234, 6); // '001234'",
    "id": "padNumber",
    "tags": [
      "string",
      "math",
      "beginner"
    ]
  },
  {
    "code": "const palindrome = str => {\n  const s = str.toLowerCase().replace(/[\\W_]/g, '');\n  return s === [...s].reverse().join('');\n};",
    "description": "Checks if the given string is a palindrome.\n\n- Normalize the string to `String.prototype.toLowerCase()` and use `String.prototype.replace()` to remove non-alphanumeric characters from it.\n- Use the spread operator (`...`) to split the normalized string into individual characters.\n- Use `Array.prototype.reverse()`, `String.prototype.join('')` and compare the result to the normalized string.",
    "example": "palindrome('taco cat'); // true",
    "id": "palindrome",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const parseCookie = str =>\n  str\n    .split(';')\n    .map(v => v.split('='))\n    .reduce((acc, v) => {\n      acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());\n      return acc;\n    }, {});",
    "description": "Parses an HTTP Cookie header string, returning an object of all cookie name-value pairs.\n\n- Use `String.prototype.split(';')` to separate key-value pairs from each other.\n- Use `Array.prototype.map()` and `String.prototype.split('=')` to separate keys from values in each pair.\n- Use `Array.prototype.reduce()` and `decodeURIComponent()` to create an object with all key-value pairs.",
    "example": "parseCookie('foo=bar; equation=E%3Dmc%5E2');\n// { foo: 'bar', equation: 'E=mc^2' }",
    "id": "parseCookie",
    "tags": [
      "browser",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);",
    "description": "Creates a function that invokes `fn` with `partials` prepended to the arguments it receives.\n\n- Use the spread operator (`...`) to prepend `partials` to the list of arguments of `fn`.",
    "example": "const greet = (greeting, name) => greeting + ' ' + name + '!';\nconst greetHello = partial(greet, 'Hello');\ngreetHello('John'); // 'Hello John!'",
    "id": "partial",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);",
    "description": "Creates a function that invokes `fn` with `partials` appended to the arguments it receives.\n\n- Use the spread operator (`...`) to append `partials` to the list of arguments of `fn`.",
    "example": "const greet = (greeting, name) => greeting + ' ' + name + '!';\nconst greetJohn = partialRight(greet, 'John');\ngreetJohn('Hello'); // 'Hello John!'",
    "id": "partialRight",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const partition = (arr, fn) =>\n  arr.reduce(\n    (acc, val, i, arr) => {\n      acc[fn(val, i, arr) ? 0 : 1].push(val);\n      return acc;\n    },\n    [[], []]\n  );",
    "description": "Groups the elements into two arrays, depending on the provided function's truthiness for each element.\n\n- Use `Array.prototype.reduce()` to create an array of two arrays.\n- Use `Array.prototype.push()` to add elements for which `fn` returns `true` to the first array and elements for which `fn` returns `false` to the second one.",
    "example": "const users = [\n  { user: 'barney', age: 36, active: false },\n  { user: 'fred', age: 40, active: true },\n];\npartition(users, o => o.active);\n// [\n//   [{ user: 'fred', age: 40, active: true }],\n//   [{ user: 'barney', age: 36, active: false }]\n// ]",
    "id": "partition",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const partitionBy = (arr, fn) =>\n  arr.reduce(\n    ({ res, last }, v, i, a) => {\n      const next = fn(v, i, a);\n      if (next !== last) res.push([v]);\n      else res[res.length - 1].push(v);\n      return { res, last: next };\n    },\n    { res: [] }\n  ).res;",
    "description": "Applies `fn` to each value in `arr`, splitting it each time the provided function returns a new value.\n\n- Use `Array.prototype.reduce()` with an accumulator object that will hold the resulting array and the last value returned from `fn`.\n- Use `Array.prototype.push()` to add each value in `arr` to the appropriate partition in the accumulator array.",
    "example": "const numbers = [1, 1, 3, 3, 4, 5, 5, 5];\npartitionBy(numbers, n => n % 2 === 0); // [[1, 1, 3, 3], [4], [5, 5, 5]]\npartitionBy(numbers, n => n); // [[1, 1], [3, 3], [4], [5, 5, 5]]",
    "id": "partitionBy",
    "tags": [
      "array",
      "object",
      "advanced"
    ]
  },
  {
    "code": "const percentile = (arr, val) =>\n  (100 *\n    arr.reduce(\n      (acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0),\n      0\n    )) /\n  arr.length;",
    "description": "Calculates the percentage of numbers in the given array that are less or equal to the given value.\n\n- Use `Array.prototype.reduce()` to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.",
    "example": "percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6); // 55",
    "id": "percentile",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const permutations = arr => {\n  if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;\n  return arr.reduce(\n    (acc, item, i) =>\n      acc.concat(\n        permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [\n          item,\n          ...val,\n        ])\n      ),\n    []\n  );\n};",
    "description": "Generates all permutations of an array's elements (contains duplicates).\n\n- Use recursion.\n- For each element in the given array, create all the partial permutations for the rest of its elements.\n- Use `Array.prototype.map()` to combine the element with each partial permutation, then `Array.prototype.reduce()` to combine all permutations in one array.\n- Base cases are for `Array.prototype.length` equal to `2` or `1`.\n- ⚠️ **WARNING**: This function's execution time increases exponentially with each array element. Anything more than 8 to 10 entries may cause your browser to hang as it tries to solve all the different combinations.",
    "example": "permutations([1, 33, 5]);\n// [ [1, 33, 5], [1, 5, 33], [33, 1, 5], [33, 5, 1], [5, 1, 33], [5, 33, 1] ]",
    "id": "permutations",
    "tags": [
      "array",
      "algorithm",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const pick = (obj, arr) =>\n  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});",
    "description": "Picks the key-value pairs corresponding to the given keys from an object.\n\n- Use `Array.prototype.reduce()` to convert the filtered/picked keys back to an object with the corresponding key-value pairs if the key exists in the object.",
    "example": "pick({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 }",
    "id": "pick",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const pickBy = (obj, fn) =>\n  Object.keys(obj)\n    .filter(k => fn(obj[k], k))\n    .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});",
    "description": "Creates an object composed of the properties the given function returns truthy for.\n\n- Use `Object.keys(obj)` and `Array.prototype.filter()`to remove the keys for which `fn` returns a falsy value.\n- Use `Array.prototype.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs.\n- The callback function is invoked with two arguments: (value, key).",
    "example": "pickBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number');\n// { 'a': 1, 'c': 3 }",
    "id": "pickBy",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const pipeAsyncFunctions = (...fns) =>\n  arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));",
    "description": "Performs left-to-right function composition for asynchronous functions.\n\n- Use `Array.prototype.reduce()` and the spread operator (`...`) to perform function composition using `Promise.prototype.then()`.\n- The functions can return a combination of normal values, `Promise`s or be `async`, returning through `await`.\n- All functions must accept a single argument.",
    "example": "const sum = pipeAsyncFunctions(\n  x => x + 1,\n  x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)),\n  x => x + 3,\n  async x => (await x) + 4\n);\n(async() => {\n  console.log(await sum(5)); // 15 (after one second)\n})();",
    "id": "pipeAsyncFunctions",
    "tags": [
      "function",
      "promise",
      "intermediate"
    ]
  },
  {
    "code": "const pipeFunctions = (...fns) =>\n  fns.reduce((f, g) => (...args) => g(f(...args)));",
    "description": "Performs left-to-right function composition.\n\n- Use `Array.prototype.reduce()` with the spread operator (`...`) to perform left-to-right function composition.\n- The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.",
    "example": "const add5 = x => x + 5;\nconst multiply = (x, y) => x * y;\nconst multiplyAndAdd5 = pipeFunctions(multiply, add5);\nmultiplyAndAdd5(5, 2); // 15",
    "id": "pipeFunctions",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const pluck = (arr, key) => arr.map(i => i[key]);",
    "description": "Converts an array of objects into an array of values corresponding to the specified `key`.\n\n- Use `Array.prototype.map()` to map the array of objects to the value of `key` for each one.",
    "example": "const simpsons = [\n  { name: 'lisa', age: 8 },\n  { name: 'homer', age: 36 },\n  { name: 'marge', age: 34 },\n  { name: 'bart', age: 10 }\n];\npluck(simpsons, 'age'); // [8, 36, 34, 10]",
    "id": "pluck",
    "tags": [
      "array",
      "object",
      "beginner"
    ]
  },
  {
    "code": "const pluralize = (val, word, plural = word + 's') => {\n  const _pluralize = (num, word, plural = word + 's') =>\n    [1, -1].includes(Number(num)) ? word : plural;\n  if (typeof val === 'object')\n    return (num, word) => _pluralize(num, word, val[word]);\n  return _pluralize(val, word, plural);\n};",
    "description": "Returns the singular or plural form of the word based on the input number, using an optional dictionary if supplied.\n\n- Use a closure to define a function that pluralizes the given `word` based on the value of `num`.\n- If `num` is either `-1` or `1`, return the singular form of the word.\n- If `num` is any other number, return the `plural` form.\n- Omit the third argument, `plural`, to use the default of the singular word + `s`, or supply a custom pluralized `word` when necessary.\n- If the first argument is an `object`, return a function which can use the supplied dictionary to resolve the correct plural form of the word.",
    "example": "pluralize(0, 'apple'); // 'apples'\npluralize(1, 'apple'); // 'apple'\npluralize(2, 'apple'); // 'apples'\npluralize(2, 'person', 'people'); // 'people'\n\nconst PLURALS = {\n  person: 'people',\n  radius: 'radii'\n};\nconst autoPluralize = pluralize(PLURALS);\nautoPluralize(2, 'person'); // 'people'",
    "id": "pluralize",
    "tags": [
      "string",
      "advanced"
    ]
  },
  {
    "code": "const powerset = arr =>\n  arr.reduce((a, v) => a.concat(a.map(r => r.concat(v))), [[]]);",
    "description": "Returns the powerset of a given array of numbers.\n\n- Use `Array.prototype.reduce()` combined with `Array.prototype.map()` to iterate over elements and combine into an array containing all combinations.",
    "example": "powerset([1, 2]); // [[], [1], [2], [1, 2]]",
    "id": "powerset",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const prefersDarkColorScheme = () =>\n  window &&\n  window.matchMedia &&\n  window.matchMedia('(prefers-color-scheme: dark)').matches;",
    "description": "Checks if the user color scheme preference is `dark`.\n\n- Use `Window.matchMedia()` with the appropriate media query to check the user color scheme preference.",
    "example": "prefersDarkColorScheme(); // true",
    "id": "prefersDarkColorScheme",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const prefersLightColorScheme = () =>\n  window &&\n  window.matchMedia &&\n  window.matchMedia('(prefers-color-scheme: light)').matches;",
    "description": "Checks if the user color scheme preference is `light`.\n\n- Use `Window.matchMedia()` with the appropriate media query to check the user color scheme preference.",
    "example": "prefersLightColorScheme(); // true",
    "id": "prefersLightColorScheme",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const prefix = prop => {\n  const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);\n  const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];\n  const i = prefixes.findIndex(\n    prefix =>\n      typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !==\n      'undefined'\n  );\n  return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null;\n};",
    "description": "Prefixes a CSS property based on the current browser.\n\n- Use `Array.prototype.findIndex()` on an array of vendor prefix strings to test if `Document.body` has one of them defined in its `CSSStyleDeclaration` object, otherwise return `null`.\n- Use `String.prototype.charAt()` and `String.prototype.toUpperCase()` to capitalize the property, which will be appended to the vendor prefix string.",
    "example": "prefix('appearance');\n// 'appearance' on a supported browser, otherwise 'webkitAppearance', 'mozAppearance', 'msAppearance' or 'oAppearance'",
    "id": "prefix",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const prettyBytes = (num, precision = 3, addSpace = true) => {\n  const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n  if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];\n  const exponent = Math.min(\n    Math.floor(Math.log10(num < 0 ? -num : num) / 3),\n    UNITS.length - 1\n  );\n  const n = Number(\n    ((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)\n  );\n  return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];\n};",
    "description": "Converts a number in bytes to a human-readable string.\n\n- Use an array dictionary of units to be accessed based on the exponent.\n- Use `Number.prototype.toPrecision()` to truncate the number to a certain number of digits.\n- Return the prettified string by building it up, taking into account the supplied options and whether it is negative or not.\n- Omit the second argument, `precision`, to use a default precision of `3` digits.\n- Omit the third argument, `addSpace`, to add space between the number and unit by default.",
    "example": "prettyBytes(1000); // '1 KB'\nprettyBytes(-27145424323.5821, 5); // '-27.145 GB'\nprettyBytes(123456789, 3, false); // '123MB'",
    "id": "prettyBytes",
    "tags": [
      "string",
      "math",
      "advanced"
    ]
  },
  {
    "code": "const primeFactors = n => {\n  let a = [],\n    f = 2;\n  while (n > 1) {\n    if (n % f === 0) {\n      a.push(f);\n      n /= f;\n    } else {\n      f++;\n    }\n  }\n  return a;\n};",
    "description": "Finds the prime factors of a given number using the trial division algorithm.\n\n- Use a `while` loop to iterate over all possible prime factors, starting with `2`.\n- If the current factor, `f`, exactly divides `n`, add `f` to the factors array and divide `n` by `f`. Otherwise, increment `f` by one.",
    "example": "primeFactors(147); // [3, 7, 7]",
    "id": "primeFactors",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const primes = num => {\n  let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),\n    sqroot = Math.floor(Math.sqrt(num)),\n    numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);\n  numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x)));\n  return arr;\n};",
    "description": "Generates primes up to a given number, using the Sieve of Eratosthenes.\n\n- Generate an array from `2` to the given number.\n- Use `Array.prototype.filter()` to filter out the values divisible by any number from `2` to the square root of the provided number.",
    "example": "primes(10); // [2, 3, 5, 7]",
    "id": "primes",
    "tags": [
      "math",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const prod = (...arr) => [...arr].reduce((acc, val) => acc * val, 1);",
    "description": "Calculates the product of two or more numbers/arrays.\n\n- Use `Array.prototype.reduce()` to multiply each value with an accumulator, initialized with a value of `1`.",
    "example": "prod(1, 2, 3, 4); // 24\nprod(...[1, 2, 3, 4]); // 24",
    "id": "prod",
    "tags": [
      "math",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const promisify = func => (...args) =>\n  new Promise((resolve, reject) =>\n    func(...args, (err, result) => (err ? reject(err) : resolve(result)))\n  );",
    "description": "Converts an asynchronous function to return a promise.\n\n- Use currying to return a function returning a `Promise` that calls the original function.\n- Use the rest operator (`...`) to pass in all the parameters.\n- **Note:** In Node 8+, you can use [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original).",
    "example": "const delay = promisify((d, cb) => setTimeout(cb, d));\ndelay(2000).then(() => console.log('Hi!')); // Promise resolves after 2s",
    "id": "promisify",
    "tags": [
      "function",
      "promise",
      "intermediate"
    ]
  },
  {
    "code": "const pull = (arr, ...args) => {\n  let argState = Array.isArray(args[0]) ? args[0] : args;\n  let pulled = arr.filter(v => !argState.includes(v));\n  arr.length = 0;\n  pulled.forEach(v => arr.push(v));\n};",
    "description": "Mutates the original array to filter out the values specified.\n\n- Use `Array.prototype.filter()` and `Array.prototype.includes()` to pull out the values that are not needed.\n- Set `Array.prototype.length` to mutate the passed in an array by resetting its length to `0`.\n- Use `Array.prototype.push()` to re-populate it with only the pulled values.",
    "example": "let myArray = ['a', 'b', 'c', 'a', 'b', 'c'];\npull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ]",
    "id": "pull",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const pullAtIndex = (arr, pullArr) => {\n  let removed = [];\n  let pulled = arr\n    .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))\n    .filter((v, i) => !pullArr.includes(i));\n  arr.length = 0;\n  pulled.forEach(v => arr.push(v));\n  return removed;\n};",
    "description": "Mutates the original array to filter out the values at the specified indexes.\nReturns the removed elements.\n\n- Use `Array.prototype.filter()` and `Array.prototype.includes()` to pull out the values that are not needed.\n- Set `Array.prototype.length` to mutate the passed in an array by resetting its length to `0`.\n- Use `Array.prototype.push()` to re-populate it with only the pulled values.\n- Use `Array.prototype.push()` to keep track of pulled values.",
    "example": "let myArray = ['a', 'b', 'c', 'd'];\nlet pulled = pullAtIndex(myArray, [1, 3]);\n// myArray = [ 'a', 'c' ] , pulled = [ 'b', 'd' ]",
    "id": "pullAtIndex",
    "tags": [
      "array",
      "advanced"
    ]
  },
  {
    "code": "const pullAtValue = (arr, pullArr) => {\n  let removed = [],\n    pushToRemove = arr.forEach((v, i) =>\n      pullArr.includes(v) ? removed.push(v) : v\n    ),\n    mutateTo = arr.filter((v, i) => !pullArr.includes(v));\n  arr.length = 0;\n  mutateTo.forEach(v => arr.push(v));\n  return removed;\n};",
    "description": "Mutates the original array to filter out the values specified.\nReturns the removed elements.\n\n- Use `Array.prototype.filter()` and `Array.prototype.includes()` to pull out the values that are not needed.\n- Set `Array.prototype.length` to mutate the passed in an array by resetting its length to `0`.\n- Use `Array.prototype.push()` to re-populate it with only the pulled values.\n- Use `Array.prototype.push()` to keep track of pulled values.",
    "example": "let myArray = ['a', 'b', 'c', 'd'];\nlet pulled = pullAtValue(myArray, ['b', 'd']);\n// myArray = [ 'a', 'c' ] , pulled = [ 'b', 'd' ]",
    "id": "pullAtValue",
    "tags": [
      "array",
      "advanced"
    ]
  },
  {
    "code": "const pullBy = (arr, ...args) => {\n  const length = args.length;\n  let fn = length > 1 ? args[length - 1] : undefined;\n  fn = typeof fn == 'function' ? (args.pop(), fn) : undefined;\n  let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val));\n  let pulled = arr.filter((v, i) => !argState.includes(fn(v)));\n  arr.length = 0;\n  pulled.forEach(v => arr.push(v));\n};",
    "description": "Mutates the original array to filter out the values specified, based on a given iterator function.\n\n- Check if the last argument provided is a function.\n- Use `Array.prototype.map()` to apply the iterator function `fn` to all array elements.\n- Use `Array.prototype.filter()` and `Array.prototype.includes()` to pull out the values that are not needed.\n- Set `Array.prototype.length` to mutate the passed in an array by resetting its length to `0`.\n- Use `Array.prototype.push()` to re-populate it with only the pulled values.",
    "example": "var myArray = [{ x: 1 }, { x: 2 }, { x: 3 }, { x: 1 }];\npullBy(myArray, [{ x: 1 }, { x: 3 }], o => o.x); // myArray = [{ x: 2 }]",
    "id": "pullBy",
    "tags": [
      "array",
      "advanced"
    ]
  },
  {
    "code": "const quarterOfYear = (date = new Date()) => [\n  Math.ceil((date.getMonth() + 1) / 3),\n  date.getFullYear()\n];",
    "description": "Returns the quarter and year to which the supplied date belongs to.\n\n- Use `Date.prototype.getMonth()` to get the current month in the range (0, 11), add `1` to map it to the range (1, 12).\n- Use `Math.ceil()` and divide the month by `3` to get the current quarter.\n- Use `Date.prototype.getFullYear()` to get the year from the given `date`.\n- Omit the argument, `date`, to use the current date by default.",
    "example": "quarterOfYear(new Date('07/10/2018')); // [ 3, 2018 ]\nquarterOfYear(); // [ 4, 2020 ]",
    "id": "quarterOfYear",
    "tags": [
      "date",
      "beginner"
    ]
  },
  {
    "code": "const queryStringToObject = url =>\n  [...new URLSearchParams(url.split('?')[1])].reduce(\n    (a, [k, v]) => ((a[k] = v), a),\n    {}\n  );",
    "description": "Generates an object from the given query string or URL.\n\n- Use `String.prototype.split()` to get the params from the given `url`.\n- Use `new URLSearchParams()` to create an appropriate object and convert it to an array of key-value pairs using the spread operator (`...`).\n- Use `Array.prototype.reduce()` to convert the array of key-value pairs into an object.",
    "example": "queryStringToObject('https://google.com?page=1&count=10');\n// {page: '1', count: '10'}",
    "id": "queryStringToObject",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const quickSort = arr => {\n  const a = [...arr];\n  if (a.length < 2) return a;\n  const pivotIndex = Math.floor(arr.length / 2);\n  const pivot = a[pivotIndex];\n  const [lo, hi] = a.reduce(\n    (acc, val, i) => {\n      if (val < pivot || (val === pivot && i != pivotIndex)) {\n        acc[0].push(val);\n      } else if (val > pivot) {\n        acc[1].push(val);\n      }\n      return acc;\n    },\n    [[], []]\n  );\n  return [...quickSort(lo), pivot, ...quickSort(hi)];\n};",
    "description": "Sorts an array of numbers, using the quicksort algorithm.\n\n- Use recursion.\n- Use the spread operator (`...`) to clone the original array, `arr`.\n- If the `length` of the array is less than `2`, return the cloned array.\n- Use `Math.floor()` to calculate the index of the pivot element.\n- Use `Array.prototype.reduce()` and `Array.prototype.push()` to split the array into two subarrays. The first one contains elements smaller than or equal to `pivot` and the second on elements greather than it. Destructure the result into two arrays.\n- Recursively call `quickSort()` on the created subarrays.",
    "example": "quickSort([1, 6, 1, 5, 3, 2, 1, 4]); // [1, 1, 1, 2, 3, 4, 5, 6]",
    "id": "quickSort",
    "tags": [
      "algorithm",
      "array",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const radsToDegrees = rad => (rad * 180.0) / Math.PI;",
    "description": "Converts an angle from radians to degrees.\n\n- Use `Math.PI` and the radian to degree formula to convert the angle from radians to degrees.",
    "example": "radsToDegrees(Math.PI / 2); // 90",
    "id": "radsToDegrees",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const randomAlphaNumeric = length => {\n  let s = '';\n  Array.from({ length }).some(() => {\n    s += Math.random().toString(36).slice(2);\n    return s.length >= length;\n  });\n  return s.slice(0, length);\n};",
    "description": "Generates a random string with the specified length.\n\n- Use `Array.from()` to create a new array with the specified `length`.\n- Use `Math.random()` generate a random floating-point number, `Number.prototype.toString(36)` to convert it to an alphanumeric string.\n- Use `String.prototype.slice(2)` to remove the integral part and decimal point from each generated number.\n- Use `Array.prototype.some()` to repeat this process as many times as required, up to `length`, as it produces a variable-length string each time.\n- Finally, use `String.prototype.slice()` to trim down the generated string if it's longer than the given `length`.",
    "example": "randomAlphaNumeric(5); // '0afad'",
    "id": "randomAlphaNumeric",
    "tags": [
      "string",
      "random",
      "advanced"
    ]
  },
  {
    "code": "const randomBoolean = () => Math.random() >= 0.5;",
    "description": "Generates a random boolean value.\n\n- Use `Math.random()` to generate a random number and check if it is greater than or equal to `0.5`.",
    "example": "randomBoolean(); // true",
    "id": "randomBoolean",
    "tags": [
      "math",
      "random",
      "beginner"
    ]
  },
  {
    "code": "const randomHexColorCode = () => {\n  let n = (Math.random() * 0xfffff * 1000000).toString(16);\n  return '#' + n.slice(0, 6);\n};",
    "description": "Generates a random hexadecimal color code.\n\n- Use `Math.random()` to generate a random 24-bit (6 * 4bits) hexadecimal number.\n- Use bit shifting and then convert it to an hexadecimal string using `Number.prototype.toString(16)`.",
    "example": "randomHexColorCode(); // '#e34155'",
    "id": "randomHexColorCode",
    "tags": [
      "math",
      "random",
      "beginner"
    ]
  },
  {
    "code": "const randomIntArrayInRange = (min, max, n = 1) =>\n  Array.from(\n    { length: n },\n    () => Math.floor(Math.random() * (max - min + 1)) + min\n  );",
    "description": "Generates an array of `n` random integers in the specified range.\n\n- Use `Array.from()` to create an empty array of the specific length.\n- Use `Math.random()` to generate random numbers and map them to the desired range, using `Math.floor()` to make them integers.",
    "example": "randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]",
    "id": "randomIntArrayInRange",
    "tags": [
      "math",
      "random",
      "intermediate"
    ]
  },
  {
    "code": "const randomIntegerInRange = (min, max) =>\n  Math.floor(Math.random() * (max - min + 1)) + min;",
    "description": "Generates a random integer in the specified range.\n\n- Use `Math.random()` to generate a random number and map it to the desired range.\n- Use `Math.floor()` to make it an integer.",
    "example": "randomIntegerInRange(0, 5); // 2",
    "id": "randomIntegerInRange",
    "tags": [
      "math",
      "random",
      "beginner"
    ]
  },
  {
    "code": "const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;",
    "description": "Generates a random number in the specified range.\n\n- Use `Math.random()` to generate a random value, map it to the desired range using multiplication.",
    "example": "randomNumberInRange(2, 10); // 6.0211363285087005",
    "id": "randomNumberInRange",
    "tags": [
      "math",
      "random",
      "beginner"
    ]
  },
  {
    "code": "const rangeGenerator = function* (start, end, step = 1) {\n  let i = start;\n  while (i < end) {\n    yield i;\n    i += step;\n  }\n};",
    "description": "Creates a generator, that generates all values in the given range using the given step.\n\n- Use a `while` loop to iterate from `start` to `end`, using `yield` to return each value and then incrementing by `step`.\n- Omit the third argument, `step`, to use a default value of `1`.",
    "example": "for (let i of rangeGenerator(6, 10)) console.log(i);\n// Logs 6, 7, 8, 9",
    "id": "rangeGenerator",
    "tags": [
      "function",
      "generator",
      "advanced"
    ]
  },
  {
    "code": "const fs = require('fs');\n\nconst readFileLines = filename =>\n  fs\n    .readFileSync(filename)\n    .toString('UTF8')\n    .split('\\n');",
    "description": "Returns an array of lines from the specified file.\n\n- Use `fs.readFileSync()` to create a `Buffer` from a file.\n- Convert buffer to string using `buf.toString(encoding)` function.\n- Use `String.prototype.split(\\n)` to create an array of lines from the contents of the file.",
    "example": "/*\ncontents of test.txt :\n  line1\n  line2\n  line3\n  ___________________________\n*/\nlet arr = readFileLines('test.txt');\nconsole.log(arr); // ['line1', 'line2', 'line3']",
    "id": "readFileLines",
    "tags": [
      "node",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));",
    "description": "Creates a function that invokes the provided function with its arguments arranged according to the specified indexes.\n\n- Use `Array.prototype.map()` to reorder arguments based on `indexes`.\n- Use the spread operator (`...`) to pass the transformed arguments to `fn`.",
    "example": "var rearged = rearg(\n  function(a, b, c) {\n    return [a, b, c];\n  },\n  [2, 0, 1]\n);\nrearged('b', 'c', 'a'); // ['a', 'b', 'c']",
    "id": "rearg",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const recordAnimationFrames = (callback, autoStart = true) => {\n  let running = false,\n    raf;\n  const stop = () => {\n    if (!running) return;\n    running = false;\n    cancelAnimationFrame(raf);\n  };\n  const start = () => {\n    if (running) return;\n    running = true;\n    run();\n  };\n  const run = () => {\n    raf = requestAnimationFrame(() => {\n      callback();\n      if (running) run();\n    });\n  };\n  if (autoStart) start();\n  return { start, stop };\n};",
    "description": "Invokes the provided callback on each animation frame.\n\n- Use recursion.\n- Provided that `running` is `true`, continue invoking `Window.requestAnimationFrame()` which invokes the provided callback.\n- Return an object with two methods `start` and `stop` to allow manual control of the recording.\n- Omit the second argument, `autoStart`, to implicitly call `start` when the function is invoked.",
    "example": "const cb = () => console.log('Animation frame fired');\nconst recorder = recordAnimationFrames(cb);\n// logs 'Animation frame fired' on each animation frame\nrecorder.stop(); // stops logging\nrecorder.start(); // starts again\nconst recorder2 = recordAnimationFrames(cb, false);\n// `start` needs to be explicitly called to begin recording frames",
    "id": "recordAnimationFrames",
    "tags": [
      "browser",
      "recursion",
      "intermediate"
    ]
  },
  {
    "code": "const redirect = (url, asLink = true) =>\n  asLink ? (window.location.href = url) : window.location.replace(url);",
    "description": "Redirects to a specified URL.\n\n- Use `Window.location.href` or `Window.location.replace()` to redirect to `url`.\n- Pass a second argument to simulate a link click (`true` - default) or an HTTP redirect (`false`).",
    "example": "redirect('https://google.com');",
    "id": "redirect",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const reduceSuccessive = (arr, fn, acc) =>\n  arr.reduce(\n    (res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res),\n    [acc]\n  );",
    "description": "Applies a function against an accumulator and each element in the array (from left to right), returning an array of successively reduced values.\n\n- Use `Array.prototype.reduce()` to apply the given function to the given array, storing each new result.",
    "example": "reduceSuccessive([1, 2, 3, 4, 5, 6], (acc, val) => acc + val, 0);\n// [0, 1, 3, 6, 10, 15, 21]",
    "id": "reduceSuccessive",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const reduceWhich = (arr, comparator = (a, b) => a - b) =>\n  arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a));",
    "description": "Returns the minimum/maximum value of an array, after applying the provided function to set the comparing rule.\n\n- Use `Array.prototype.reduce()` in combination with the `comparator` function to get the appropriate element in the array.\n- Omit the second argument, `comparator`, to use the default one that returns the minimum element in the array.",
    "example": "reduceWhich([1, 3, 2]); // 1\nreduceWhich([1, 3, 2], (a, b) => b - a); // 3\nreduceWhich(\n  [\n    { name: 'Tom', age: 12 },\n    { name: 'Jack', age: 18 },\n    { name: 'Lucy', age: 9 }\n  ],\n  (a, b) => a.age - b.age\n); // {name: 'Lucy', age: 9}",
    "id": "reduceWhich",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const reducedFilter = (data, keys, fn) =>\n  data.filter(fn).map(el =>\n    keys.reduce((acc, key) => {\n      acc[key] = el[key];\n      return acc;\n    }, {})\n  );",
    "description": "Filters an array of objects based on a condition while also filtering out unspecified keys.\n\n- Use `Array.prototype.filter()` to filter the array based on the predicate `fn` so that it returns the objects for which the condition returned a truthy value.\n- On the filtered array, use `Array.prototype.map()` to return the new object.\n- Use `Array.prototype.reduce()` to filter out the keys which were not supplied as the `keys` argument.",
    "example": "const data = [\n  {\n    id: 1,\n    name: 'john',\n    age: 24\n  },\n  {\n    id: 2,\n    name: 'mike',\n    age: 50\n  }\n];\nreducedFilter(data, ['id', 'name'], item => item.age > 24);\n// [{ id: 2, name: 'mike'}]",
    "id": "reducedFilter",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const reject = (pred, array) => array.filter((...args) => !pred(...args));",
    "description": "Filters an array's values based on a predicate function, returning only values for which the predicate function returns `false`.\n\n- Use `Array.prototype.filter()` in combination with the predicate function, `pred`, to return only the values for which it returns `false`.",
    "example": "reject(x => x % 2 === 0, [1, 2, 3, 4, 5]); // [1, 3, 5]\nreject(word => word.length > 4, ['Apple', 'Pear', 'Kiwi', 'Banana']);\n// ['Pear', 'Kiwi']",
    "id": "reject",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const remove = (arr, func) =>\n  Array.isArray(arr)\n    ? arr.filter(func).reduce((acc, val) => {\n      arr.splice(arr.indexOf(val), 1);\n      return acc.concat(val);\n    }, [])\n    : [];",
    "description": "Mutates an array by removing elements for which the given function returns `false`.\n\n- Use `Array.prototype.filter()` to find array elements that return truthy values.\n- Use `Array.prototype.reduce()` to remove elements using `Array.prototype.splice()`.\n- The callback function is invoked with three arguments (value, index, array).",
    "example": "remove([1, 2, 3, 4], n => n % 2 === 0); // [2, 4]",
    "id": "remove",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const removeAccents = str =>\n  str.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');",
    "description": "Removes accents from strings.\n\n- Use `String.prototype.normalize()` to convert the string to a normalized Unicode format.\n- Use `String.prototype.replace()` to replace diacritical marks in the given Unicode range by empty strings.",
    "example": "removeAccents('Antoine de Saint-Exupéry'); // 'Antoine de Saint-Exupery'",
    "id": "removeAccents",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const removeClass = (el, className) => el.classList.remove(className);",
    "description": "Removes a class from an HTML element.\n\n- Use `Element.classList` and `DOMTokenList.remove()` to remove the specified class from the element.",
    "example": "removeClass(document.querySelector('p.special'), 'special');\n// The paragraph will not have the 'special' class anymore",
    "id": "removeClass",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const removeElement = el => el.parentNode.removeChild(el);",
    "description": "Removes an element from the DOM.\n\n- Use `Element.parentNode` to get the given element's parent node.\n- Use `Element.removeChild()` to remove the given element from its parent node.",
    "example": "removeElement(document.querySelector('#my-element'));\n// Removes #my-element from the DOM",
    "id": "removeElement",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const removeEventListenerAll = (\n  targets,\n  type,\n  listener,\n  options,\n  useCapture\n) => {\n  targets.forEach(target =>\n    target.removeEventListener(type, listener, options, useCapture)\n  );\n};",
    "description": "Detaches an event listener from all the provided targets.\n\n- Use `Array.prototype.forEach()` and `EventTarget.removeEventListener()` to detach the provided `listener` for the given event `type` from all `targets`.",
    "example": "const linkListener = () => console.log('Clicked a link');\ndocument.querySelector('a').addEventListener('click', linkListener);\nremoveEventListenerAll(document.querySelectorAll('a'), 'click', linkListener);",
    "id": "removeEventListenerAll",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const removeNonASCII = str => str.replace(/[^\\x20-\\x7E]/g, '');",
    "description": "Removes non-printable ASCII characters.\n\n- Use `String.prototype.replace()` with a regular expression to remove non-printable ASCII characters.",
    "example": "removeNonASCII('äÄçÇéÉêlorem-ipsumöÖÐþúÚ'); // 'lorem-ipsum'",
    "id": "removeNonASCII",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const removeWhitespace = str => str.replace(/\\s+/g, '');",
    "description": "Returns a string with whitespaces removed.\n\n- Use `String.prototype.replace()` with a regular expression to replace all occurrences of whitespace characters with an empty string.",
    "example": "removeWhitespace('Lorem ipsum.\\n Dolor sit amet. ');\n// 'Loremipsum.Dolorsitamet.'",
    "id": "removeWhitespace",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const renameKeys = (keysMap, obj) =>\n  Object.keys(obj).reduce(\n    (acc, key) => ({\n      ...acc,\n      ...{ [keysMap[key] || key]: obj[key] }\n    }),\n    {}\n  );",
    "description": "Replaces the names of multiple object keys with the values provided.\n\n- Use `Object.keys()` in combination with `Array.prototype.reduce()` and the spread operator (`...`) to get the object's keys and rename them according to `keysMap`.",
    "example": "const obj = { name: 'Bobo', job: 'Front-End Master', shoeSize: 100 };\nrenameKeys({ name: 'firstName', job: 'passion' }, obj);\n// { firstName: 'Bobo', passion: 'Front-End Master', shoeSize: 100 }",
    "id": "renameKeys",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const renderElement = ({ type, props = {} }, container) => {\n  const isTextElement = !type;\n  const element = isTextElement\n    ? document.createTextNode('')\n    : document.createElement(type);\n\n  const isListener = p => p.startsWith('on');\n  const isAttribute = p => !isListener(p) && p !== 'children';\n\n  Object.keys(props).forEach(p => {\n    if (isAttribute(p)) element[p] = props[p];\n    if (!isTextElement && isListener(p))\n      element.addEventListener(p.toLowerCase().slice(2), props[p]);\n  });\n\n  if (!isTextElement && props.children && props.children.length)\n    props.children.forEach(childElement =>\n      renderElement(childElement, element)\n    );\n\n  container.appendChild(element);\n};",
    "description": "Renders the given DOM tree in the specified DOM element.\n\n- Destructure the first argument into `type` and `props`. Use `type` to determine if the given element is a text element.\n- Based on the element's `type`, use either `Document.createTextNode()` or `Document.createElement()` to create the DOM element.\n- Use `Object.keys()` to add attributes to the DOM element and set event listeners, as necessary.\n- Use recursion to render `props.children`, if any.\n- Finally, use `Node.appendChild()` to append the DOM element to the specified `container`.",
    "example": "const myElement = {\n  type: 'button',\n  props: {\n    type: 'button',\n    className: 'btn',\n    onClick: () => alert('Clicked'),\n    children: [{ props: { nodeValue: 'Click me' } }]\n  }\n};\n\nrenderElement(myElement, document.body);",
    "id": "renderElement",
    "tags": [
      "browser",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const repeatGenerator = function* (val) {\n  let v = val;\n  while (true) {\n    let newV = yield v;\n    if (newV !== undefined) v = newV;\n  }\n};",
    "description": "Creates a generator, repeating the given value indefinitely.\n\n- Use a non-terminating `while` loop, that will `yield` a value every time `Generator.prototype.next()` is called.\n- Use the return value of the `yield` statement to update the returned value if the passed value is not `undefined`.",
    "example": "const repeater = repeatGenerator(5);\nrepeater.next(); // { value: 5, done: false }\nrepeater.next(); // { value: 5, done: false }\nrepeater.next(4); // { value: 4, done: false }\nrepeater.next(); // { value: 4, done: false }",
    "id": "repeatGenerator",
    "tags": [
      "function",
      "generator",
      "advanced"
    ]
  },
  {
    "code": "const replaceLast = (str, pattern, replacement) => {\n  const match =\n    typeof pattern === 'string'\n      ? pattern\n      : (str.match(new RegExp(pattern.source, 'g')) || []).slice(-1)[0];\n  if (!match) return str;\n  const last = str.lastIndexOf(match);\n  return last !== -1\n    ? \\`\\${str.slice(0, last)}\\${replacement}\\${str.slice(last + match.length)}\\`\n    : str;\n};",
    "description": "Replaces the last occurence of a pattern in a string.\n\n- Use `typeof` to determine if `pattern` is a string or a regular expression.\n- If the `pattern` is a string, use it as the `match`.\n- Otherwise, use the `RegeExp` constructor to create a new regular expression using the `RegExp.source` of the `pattern` and adding the `'g'` flag to it. Use `String.prototype.match()` and `Array.prototype.slice()` to get the last match, if any.\n- Use `String.prototype.lastIndexOf()` to find the last occurence of the match in the string.\n- If a match is found, use `String.prototype.slice()` and a template literal to replace the matching substring with the given `replacement`.\n- If no match is found, return the original string.",
    "example": "replaceLast('abcabdef', 'ab', 'gg'); // 'abcggdef'\nreplaceLast('abcabdef', /ab/, 'gg'); // 'abcggdef'\nreplaceLast('abcabdef', 'ad', 'gg'); // 'abcabdef'\nreplaceLast('abcabdef', /ad/, 'gg'); // 'abcabdef'",
    "id": "replaceLast",
    "tags": [
      "string",
      "regexp",
      "advanced"
    ]
  },
  {
    "code": "const requireUncached = module => {\n  delete require.cache[require.resolve(module)];\n  return require(module);\n};",
    "description": "Loads a module after removing it from the cache (if exists).\n\n- Use `delete` to remove the module from the cache (if exists).\n- Use `require()` to load the module again.",
    "example": "const fs = requireUncached('fs'); // 'fs' will be loaded fresh every time",
    "id": "requireUncached",
    "tags": [
      "node",
      "advanced"
    ]
  },
  {
    "code": "const reverseNumber = n => \n  parseFloat(\\`\\${n}\\`.split('').reverse().join('')) * Math.sign(n);",
    "description": "Reverses a number.\n\n- Use `Object.prototype.toString()` to convert `n` to a string.\n- Use `String.prototype.split('')`, `Array.prototype.reverse()` and `String.prototype.join('')` to get the reversed value of `n` as a string.\n- Use `parseFloat()` to convert the string to a number and `Math.sign()` to preserve its sign.",
    "example": "reverseNumber(981); // 189\nreverseNumber(-500); // -5\nreverseNumber(73.6); // 6.37\nreverseNumber(-5.23); // -32.5",
    "id": "reverseNumber",
    "tags": [
      "math",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const reverseString = str => [...str].reverse().join('');",
    "description": "Reverses a string.\n\n- Use the spread operator (`...`) and `Array.prototype.reverse()` to reverse the order of the characters in the string.\n- Combine characters to get a string using `String.prototype.join('')`.",
    "example": "reverseString('foobar'); // 'raboof'",
    "id": "reverseString",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const round = (n, decimals = 0) => \n  Number(\\`\\${Math.round(\\`\\${n}e\\${decimals}\\`)}e-\\${decimals}\\`);",
    "description": "Rounds a number to a specified amount of digits.\n\n- Use `Math.round()` and template literals to round the number to the specified number of digits.\n- Omit the second argument, `decimals`, to round to an integer.",
    "example": "round(1.005, 2); // 1.01",
    "id": "round",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const runAsync = fn => {\n  const worker = new Worker(\n    URL.createObjectURL(new Blob([\\`postMessage((\\${fn})());\\`]), {\n      type: 'application/javascript; charset=utf-8'\n    })\n  );\n  return new Promise((res, rej) => {\n    worker.onmessage = ({ data }) => {\n      res(data), worker.terminate();\n    };\n    worker.onerror = err => {\n      rej(err), worker.terminate();\n    };\n  });\n};",
    "description": "Runs a function in a separate thread by using a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers), allowing long running functions to not block the UI.\n\n- Create a `new Worker()` using a `Blob` object URL, the contents of which should be the stringified version of the supplied function.\n- Immediately post the return value of calling the function back.\n- Return a `new Promise()`, listening for `onmessage` and `onerror` events and resolving the data posted back from the worker, or throwing an error.",
    "example": "const longRunningFunction = () => {\n  let result = 0;\n  for (let i = 0; i < 1000; i++)\n    for (let j = 0; j < 700; j++)\n      for (let k = 0; k < 300; k++) result = result + i + j + k;\n\n  return result;\n};\n/*\n  NOTE: Since the function is running in a different context, closures are not supported.\n  The function supplied to `runAsync` gets stringified, so everything becomes literal.\n  All variables and functions must be defined inside.\n*/\nrunAsync(longRunningFunction).then(console.log); // 209685000000\nrunAsync(() => 10 ** 3).then(console.log); // 1000\nlet outsideVariable = 50;\nrunAsync(() => typeof outsideVariable).then(console.log); // 'undefined'",
    "id": "runAsync",
    "tags": [
      "browser",
      "function",
      "promise",
      "advanced"
    ]
  },
  {
    "code": "const runPromisesInSeries = ps =>\n  ps.reduce((p, next) => p.then(next), Promise.resolve());",
    "description": "Runs an array of promises in series.\n\n- Use `Array.prototype.reduce()` to create a promise chain, where each promise returns the next promise when resolved.",
    "example": "const delay = d => new Promise(r => setTimeout(r, d));\nrunPromisesInSeries([() => delay(1000), () => delay(2000)]);\n// Executes each promise sequentially, taking a total of 3 seconds to complete",
    "id": "runPromisesInSeries",
    "tags": [
      "function",
      "promise",
      "intermediate"
    ]
  },
  {
    "code": "const sample = arr => arr[Math.floor(Math.random() * arr.length)];",
    "description": "Gets a random element from an array.\n\n- Use `Math.random()` to generate a random number.\n- Multiply it by `Array.prototype.length` and round it off to the nearest whole number using `Math.floor()`.\n- This method also works with strings.",
    "example": "sample([3, 7, 9, 11]); // 9",
    "id": "sample",
    "tags": [
      "array",
      "string",
      "random",
      "beginner"
    ]
  },
  {
    "code": "const sampleSize = ([...arr], n = 1) => {\n  let m = arr.length;\n  while (m) {\n    const i = Math.floor(Math.random() * m--);\n    [arr[m], arr[i]] = [arr[i], arr[m]];\n  }\n  return arr.slice(0, n);\n};",
    "description": "Gets `n` random elements at unique keys from an array up to the size of the array.\n\n- Shuffle the array using the [Fisher-Yates algorithm](https://github.com/30-seconds/30-seconds-of-code#shuffle).\n- Use `Array.prototype.slice()` to get the first `n` elements.\n- Omit the second argument, `n`, to get only one element at random from the array.",
    "example": "sampleSize([1, 2, 3], 2); // [3, 1]\nsampleSize([1, 2, 3], 4); // [2, 3, 1]",
    "id": "sampleSize",
    "tags": [
      "array",
      "random",
      "intermediate"
    ]
  },
  {
    "code": "const scrollToTop = () => {\n  const c = document.documentElement.scrollTop || document.body.scrollTop;\n  if (c > 0) {\n    window.requestAnimationFrame(scrollToTop);\n    window.scrollTo(0, c - c / 8);\n  }\n};",
    "description": "Smooth-scrolls to the top of the page.\n\n- Get distance from top using `Document.documentElement` or `Document.body` and `Element.scrollTop`.\n- Scroll by a fraction of the distance from the top.\n- Use `Window.requestAnimationFrame()` to animate the scrolling.",
    "example": "scrollToTop(); // Smooth-scrolls to the top of the page",
    "id": "scrollToTop",
    "tags": [
      "browser",
      "intermediate"
    ]
  },
  {
    "code": "const sdbm = str => {\n  let arr = str.split('');\n  return arr.reduce(\n    (hashCode, currentVal) =>\n      (hashCode =\n        currentVal.charCodeAt(0) +\n        (hashCode << 6) +\n        (hashCode << 16) -\n        hashCode),\n    0\n  );\n};",
    "description": "Hashes the input string into a whole number.\n\n- Use `String.prototype.split('')` and `Array.prototype.reduce()` to create a hash of the input string, utilizing bit shifting.",
    "example": "sdbm('name'); // -3521204949",
    "id": "sdbm",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const selectionSort = arr => {\n  const a = [...arr];\n  for (let i = 0; i < a.length; i++) {\n    const min = a\n      .slice(i + 1)\n      .reduce((acc, val, j) => (val < a[acc] ? j + i + 1 : acc), i);\n    if (min !== i) [a[i], a[min]] = [a[min], a[i]];\n  }\n  return a;\n};",
    "description": "Sorts an array of numbers, using the selection sort algorithm.\n\n- Use the spread operator (`...`) to clone the original array, `arr`.\n- Use a `for` loop to iterate over elements in the array.\n- Use `Array.prototype.slice()` and `Array.prototype.reduce()` to find the index of the minimum element in the subarray to the right of the current index. Perform a swap, if necessary.",
    "example": "selectionSort([5, 1, 4, 2, 3]); // [1, 2, 3, 4, 5]",
    "id": "selectionSort",
    "tags": [
      "algorithm",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const serializeCookie = (name, val) =>\n  \\`\\${encodeURIComponent(name)}=\\${encodeURIComponent(val)}\\`;",
    "description": "Serializes a cookie name-value pair into a Set-Cookie header string.\n\n- Use template literals and `encodeURIComponent()` to create the appropriate string.",
    "example": "serializeCookie('foo', 'bar'); // 'foo=bar'",
    "id": "serializeCookie",
    "tags": [
      "browser",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const serializeForm = form =>\n  Array.from(new FormData(form), field =>\n    field.map(encodeURIComponent).join('=')\n  ).join('&');",
    "description": "Encodes a set of form elements as a query string.\n\n- Use the `FormData` constructor to convert the HTML `form` to `FormData`.\n- Use `Array.from()` to convert to an array, passing a map function as the second argument.\n- Use `Array.prototype.map()` and `encodeURIComponent()` to encode each field's value.\n- Use `Array.prototype.join()` with appropriate arguments to produce an appropriate query string.",
    "example": "serializeForm(document.querySelector('#form'));\n// email=test%40email.com&name=Test%20Name",
    "id": "serializeForm",
    "tags": [
      "browser",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const setStyle = (el, rule, val) => (el.style[rule] = val);",
    "description": "Sets the value of a CSS rule for the specified HTML element.\n\n- Use `ElementCSSInlineStyle.style` to set the value of the CSS `rule` for the specified element to `val`.",
    "example": "setStyle(document.querySelector('p'), 'font-size', '20px');\n// The first <p> element on the page will have a font-size of 20px",
    "id": "setStyle",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const shallowClone = obj => Object.assign({}, obj);",
    "description": "Creates a shallow clone of an object.\n\n- Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original.",
    "example": "const a = { x: true, y: 1 };\nconst b = shallowClone(a); // a !== b",
    "id": "shallowClone",
    "tags": [
      "object",
      "beginner"
    ]
  },
  {
    "code": "const shank = (arr, index = 0, delCount = 0, ...elements) =>\n  arr\n    .slice(0, index)\n    .concat(elements)\n    .concat(arr.slice(index + delCount));",
    "description": "Has the same functionality as [`Array.prototype.splice()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice), but returning a new array instead of mutating the original array.\n\n- Use `Array.prototype.slice()` and `Array.prototype.concat()` to get an array with the new contents after removing existing elements and/or adding new elements.\n- Omit the second argument, `index`, to start at `0`.\n- Omit the third argument, `delCount`, to remove `0` elements.\n- Omit the fourth argument, `elements`, in order to not add any new elements.",
    "example": "const names = ['alpha', 'bravo', 'charlie'];\nconst namesAndDelta = shank(names, 1, 0, 'delta');\n// [ 'alpha', 'delta', 'bravo', 'charlie' ]\nconst namesNoBravo = shank(names, 1, 1); // [ 'alpha', 'charlie' ]\nconsole.log(names); // ['alpha', 'bravo', 'charlie']",
    "id": "shank",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const show = (...el) => [...el].forEach(e => (e.style.display = ''));",
    "description": "Shows all the elements specified.\n\n- Use the spread operator (`...`) and `Array.prototype.forEach()` to clear the `display` property for each element specified.",
    "example": "show(...document.querySelectorAll('img'));\n// Shows all <img> elements on the page",
    "id": "show",
    "tags": [
      "browser",
      "css",
      "beginner"
    ]
  },
  {
    "code": "const shuffle = ([...arr]) => {\n  let m = arr.length;\n  while (m) {\n    const i = Math.floor(Math.random() * m--);\n    [arr[m], arr[i]] = [arr[i], arr[m]];\n  }\n  return arr;\n};",
    "description": "Randomizes the order of the values of an array, returning a new array.\n\n- Use the [Fisher-Yates algorithm](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Fisher_and_Yates'_original_method) to reorder the elements of the array.",
    "example": "const foo = [1, 2, 3];\nshuffle(foo); // [2, 3, 1], foo = [1, 2, 3]",
    "id": "shuffle",
    "tags": [
      "array",
      "random",
      "algorithm",
      "intermediate"
    ]
  },
  {
    "code": "const similarity = (arr, values) => arr.filter(v => values.includes(v));",
    "description": "Returns an array of elements that appear in both arrays.\n\n- Use `Array.prototype.includes()` to determine values that are not part of `values`.\n- Use `Array.prototype.filter()` to remove them.",
    "example": "similarity([1, 2, 3], [1, 2, 4]); // [1, 2]",
    "id": "similarity",
    "tags": [
      "array",
      "math",
      "beginner"
    ]
  },
  {
    "code": "const size = val =>\n  Array.isArray(val)\n    ? val.length\n    : val && typeof val === 'object'\n      ? val.size || val.length || Object.keys(val).length\n      : typeof val === 'string'\n        ? new Blob([val]).size\n        : 0;",
    "description": "Gets the size of an array, object or string.\n\n- Get type of `val` (`array`, `object` or `string`).\n- Use `Array.prototype.length` property for arrays.\n- Use `length` or `size` value if available or number of keys for objects.\n- Use `size` of a [`Blob` object](https://developer.mozilla.org/en-US/docs/Web/API/Blob) created from `val` for strings.\n- Split strings into array of characters with `split('')` and return its length.",
    "example": "size([1, 2, 3, 4, 5]); // 5\nsize('size'); // 4\nsize({ one: 1, two: 2, three: 3 }); // 3",
    "id": "size",
    "tags": [
      "object",
      "array",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));",
    "description": "Delays the execution of an asynchronous function.\n\n- Delay executing part of an `async` function, by putting it to sleep, returning a `new Promise()`.",
    "example": "async function sleepyWork() {\n  console.log(\"I'm going to sleep for 1 second.\");\n  await sleep(1000);\n  console.log('I woke up after 1 second.');\n}",
    "id": "sleep",
    "tags": [
      "function",
      "promise",
      "intermediate"
    ]
  },
  {
    "code": "const slugify = str =>\n  str\n    .toLowerCase()\n    .trim()\n    .replace(/[^\\w\\s-]/g, '')\n    .replace(/[\\s_-]+/g, '-')\n    .replace(/^-+|-+$/g, '');",
    "description": "Converts a string to a URL-friendly slug.\n\n- Use `String.prototype.toLowerCase()` and `String.prototype.trim()` to normalize the string.\n- Use `String.prototype.replace()` to replace spaces, dashes and underscores with `-` and remove special characters.",
    "example": "slugify('Hello World!'); // 'hello-world'",
    "id": "slugify",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const smoothScroll = element =>\n  document.querySelector(element).scrollIntoView({\n    behavior: 'smooth'\n  });",
    "description": "Smoothly scrolls the element on which it's called into the visible area of the browser window.\n\n- Use `Element.scrollIntoView()` to scroll the element.\n- Use `{ behavior: 'smooth' }` to scroll smoothly.",
    "example": "smoothScroll('#fooBar'); // scrolls smoothly to the element with the id fooBar\nsmoothScroll('.fooBar');\n// scrolls smoothly to the first element with a class of fooBar",
    "id": "smoothScroll",
    "tags": [
      "browser",
      "css",
      "intermediate"
    ]
  },
  {
    "code": "const sortCharactersInString = str =>\n  [...str].sort((a, b) => a.localeCompare(b)).join('');",
    "description": "Alphabetically sorts the characters in a string.\n\n- Use the spread operator (`...`), `Array.prototype.sort()` and  `String.prototype.localeCompare()` to sort the characters in `str`.\n- Recombine using `String.prototype.join('')`.",
    "example": "sortCharactersInString('cabbage'); // 'aabbceg'",
    "id": "sortCharactersInString",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const sortedIndex = (arr, n) => {\n  const isDescending = arr[0] > arr[arr.length - 1];\n  const index = arr.findIndex(el => (isDescending ? n >= el : n <= el));\n  return index === -1 ? arr.length : index;\n};",
    "description": "Finds the lowest index at which a value should be inserted into an array in order to maintain its sorting order.\n\n- Loosely check if the array is sorted in descending order.\n- Use `Array.prototype.findIndex()` to find the appropriate index where the element should be inserted.",
    "example": "sortedIndex([5, 3, 2, 1], 4); // 1\nsortedIndex([30, 50], 40); // 1",
    "id": "sortedIndex",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const sortedIndexBy = (arr, n, fn) => {\n  const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);\n  const val = fn(n);\n  const index = arr.findIndex(el =>\n    isDescending ? val >= fn(el) : val <= fn(el)\n  );\n  return index === -1 ? arr.length : index;\n};",
    "description": "Finds the lowest index at which a value should be inserted into an array in order to maintain its sorting order, based on the provided iterator function.\n\n- Loosely check if the array is sorted in descending order.\n- Use `Array.prototype.findIndex()` to find the appropriate index where the element should be inserted, based on the iterator function `fn`.",
    "example": "sortedIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 0",
    "id": "sortedIndexBy",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const sortedLastIndex = (arr, n) => {\n  const isDescending = arr[0] > arr[arr.length - 1];\n  const index = arr\n    .reverse()\n    .findIndex(el => (isDescending ? n <= el : n >= el));\n  return index === -1 ? 0 : arr.length - index;\n};",
    "description": "Finds the highest index at which a value should be inserted into an array in order to maintain its sort order.\n\n- Loosely check if the array is sorted in descending order.\n- Use `Array.prototype.reverse()` and `Array.prototype.findIndex()` to find the appropriate last index where the element should be inserted.",
    "example": "sortedLastIndex([10, 20, 30, 30, 40], 30); // 4",
    "id": "sortedLastIndex",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const sortedLastIndexBy = (arr, n, fn) => {\n  const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);\n  const val = fn(n);\n  const index = arr\n    .map(fn)\n    .reverse()\n    .findIndex(el => (isDescending ? val <= el : val >= el));\n  return index === -1 ? 0 : arr.length - index;\n};",
    "description": "Finds the highest index at which a value should be inserted into an array in order to maintain its sort order, based on a provided iterator function.\n\n- Loosely check if the array is sorted in descending order.\n- Use `Array.prototype.map()` to apply the iterator function to all elements of the array.\n- Use `Array.prototype.reverse()` and `Array.prototype.findIndex()` to find the appropriate last index where the element should be inserted, based on the provided iterator function.",
    "example": "sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1",
    "id": "sortedLastIndexBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const splitLines = str => str.split(/\\r?\\n/);",
    "description": "Splits a multiline string into an array of lines.\n\n- Use `String.prototype.split()` and a regular expression to match line breaks and create an array.",
    "example": "splitLines('This\\nis a\\nmultiline\\nstring.\\n');\n// ['This', 'is a', 'multiline', 'string.' , '']",
    "id": "splitLines",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const spreadOver = fn => argsArr => fn(...argsArr);",
    "description": "Takes a variadic function and returns a function that accepts an array of arguments.\n\n- Use a closure and the spread operator (`...`) to map the array of arguments to the inputs of the function.",
    "example": "const arrayMax = spreadOver(Math.max);\narrayMax([1, 2, 3]); // 3",
    "id": "spreadOver",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const stableSort = (arr, compare) =>\n  arr\n    .map((item, index) => ({ item, index }))\n    .sort((a, b) => compare(a.item, b.item) || a.index - b.index)\n    .map(({ item }) => item);",
    "description": "Performs stable sorting of an array, preserving the initial indexes of items when their values are the same.\n\n- Use `Array.prototype.map()` to pair each element of the input array with its corresponding index.\n- Use `Array.prototype.sort()` and a `compare` function to sort the list, preserving their initial order if the items compared are equal.\n- Use `Array.prototype.map()` to convert back to the initial array items.\n- Does not mutate the original array, but returns a new array instead.",
    "example": "const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\nconst stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]",
    "id": "stableSort",
    "tags": [
      "array",
      "advanced"
    ]
  },
  {
    "code": "const standardDeviation = (arr, usePopulation = false) => {\n  const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;\n  return Math.sqrt(\n    arr\n      .reduce((acc, val) => acc.concat((val - mean) ** 2), [])\n      .reduce((acc, val) => acc + val, 0) /\n      (arr.length - (usePopulation ? 0 : 1))\n  );\n};",
    "description": "Calculates the standard deviation of an array of numbers.\n\n- Use `Array.prototype.reduce()` to calculate the mean, variance and the sum of the variance of the values and determine the standard deviation.\n- Omit the second argument, `usePopulation`, to get the sample standard deviation or set it to `true` to get the population standard deviation.",
    "example": "standardDeviation([10, 2, 38, 23, 38, 23, 21]); // 13.284434142114991 (sample)\nstandardDeviation([10, 2, 38, 23, 38, 23, 21], true);\n// 12.29899614287479 (population)",
    "id": "standardDeviation",
    "tags": [
      "math",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const stringPermutations = str => {\n  if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];\n  return str\n    .split('')\n    .reduce(\n      (acc, letter, i) =>\n        acc.concat(\n          stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(\n            val => letter + val\n          )\n        ),\n      []\n    );\n};",
    "description": "Generates all permutations of a string (contains duplicates).\n\n- Use recursion.\n- For each letter in the given string, create all the partial permutations for the rest of its letters.\n- Use `Array.prototype.map()` to combine the letter with each partial permutation.\n- Use `Array.prototype.reduce()` to combine all permutations in one array.\n- Base cases are for `String.prototype.length` equal to `2` or `1`.\n- ⚠️ **WARNING**: The execution time increases exponentially with each character. Anything more than 8 to 10 characters will cause your environment to hang as it tries to solve all the different combinations.",
    "example": "stringPermutations('abc'); // ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']",
    "id": "stringPermutations",
    "tags": [
      "string",
      "recursion",
      "advanced"
    ]
  },
  {
    "code": "const stringifyCircularJSON = obj => {\n  const seen = new WeakSet();\n  return JSON.stringify(obj, (k, v) => {\n    if (v !== null && typeof v === 'object') {\n      if (seen.has(v)) return;\n      seen.add(v);\n    }\n    return v;\n  });\n};",
    "description": "Serializes a JSON object containing circular references into a JSON format.\n\n- Create a `new WeakSet()` to store and check seen values, using `WeakSet.prototype.add()` and `WeakSet.prototype.has()`.\n- Use `JSON.stringify()` with a custom replacer function that omits values already in `seen`, adding new values as necessary.\n- ⚠️ **NOTICE:** This function finds and removes circular references, which causes circular data loss in the serialized JSON.",
    "example": "const obj = { n: 42 };\nobj.obj = obj;\nstringifyCircularJSON(obj); // '{\"n\": 42}'",
    "id": "stringifyCircularJSON",
    "tags": [
      "object",
      "advanced"
    ]
  },
  {
    "code": "const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');",
    "description": "Removes HTML/XML tags from string.\n\n- Use a regular expression to remove HTML/XML tags from a string.",
    "example": "stripHTMLTags('<p><em>lorem</em> <strong>ipsum</strong></p>'); // 'lorem ipsum'",
    "id": "stripHTMLTags",
    "tags": [
      "string",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const subSet = (a, b) => {\n  const sA = new Set(a), sB = new Set(b);\n  return [...sA].every(v => sB.has(v));\n};",
    "description": "Checks if the first iterable is a subset of the second one, excluding duplicate values.\n\n- Use the `new Set()` constructor to create a new `Set` object from each iterable.\n- Use `Array.prototype.every()` and `Set.prototype.has()` to check that each value in the first iterable is contained in the second one.",
    "example": "subSet(new Set([1, 2]), new Set([1, 2, 3, 4])); // true\nsubSet(new Set([1, 5]), new Set([1, 2, 3, 4])); // false",
    "id": "subSet",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);",
    "description": "Calculates the sum of two or more numbers/arrays.\n\n- Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`.",
    "example": "sum(1, 2, 3, 4); // 10\nsum(...[1, 2, 3, 4]); // 10",
    "id": "sum",
    "tags": [
      "math",
      "array",
      "beginner"
    ]
  },
  {
    "code": "const sumBy = (arr, fn) =>\n  arr\n    .map(typeof fn === 'function' ? fn : val => val[fn])\n    .reduce((acc, val) => acc + val, 0);",
    "description": "Calculates the sum of an array, after mapping each element to a value using the provided function.\n\n- Use `Array.prototype.map()` to map each element to the value returned by `fn`.\n- Use `Array.prototype.reduce()` to add each value to an accumulator, initialized with a value of `0`.",
    "example": "sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], x => x.n); // 20\nsumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 20",
    "id": "sumBy",
    "tags": [
      "math",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const sumN = n => (n * (n + 1)) / 2;",
    "description": "Sums all the numbers between `1` and `n`.\n\n- Use the formula `(n * (n + 1)) / 2` to get the sum of all the numbers between 1 and `n`.",
    "example": "sumN(100); // 5050",
    "id": "sumN",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const sumPower = (end, power = 2, start = 1) =>\n  Array(end + 1 - start)\n    .fill(0)\n    .map((x, i) => (i + start) ** power)\n    .reduce((a, b) => a + b, 0);",
    "description": "Calculates the sum of the powers of all the numbers from `start` to `end` (both inclusive).\n\n- Use `Array.prototype.fill()` to create an array of all the numbers in the target range.\n- Use `Array.prototype.map()` and the exponent operator (`**`) to raise them to `power` and `Array.prototype.reduce()` to add them together.\n- Omit the second argument, `power`, to use a default power of `2`.\n- Omit the third argument, `start`, to use a default starting value of `1`.",
    "example": "sumPower(10); // 385\nsumPower(10, 3); // 3025\nsumPower(10, 3, 5); // 2925",
    "id": "sumPower",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const superSet = (a, b) => {\n  const sA = new Set(a), sB = new Set(b);\n  return [...sB].every(v => sA.has(v));\n};",
    "description": "Checks if the first iterable is a superset of the second one, excluding duplicate values.\n\n- Use the `new Set()` constructor to create a new `Set` object from each iterable.\n- Use `Array.prototype.every()` and `Set.prototype.has()` to check that each value in the second iterable is contained in the first one.",
    "example": "superSet(new Set([1, 2, 3, 4]), new Set([1, 2])); // true\nsuperSet(new Set([1, 2, 3, 4]), new Set([1, 5])); // false",
    "id": "superSet",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const supportsTouchEvents = () =>\n  window && 'ontouchstart' in window;",
    "description": "Checks if touch events are supported.\n\n- Check if `'ontouchstart'` exists in `window`.",
    "example": "supportsTouchEvents(); // true",
    "id": "supportsTouchEvents",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const swapCase = str =>\n  [...str]\n    .map(c => (c === c.toLowerCase() ? c.toUpperCase() : c.toLowerCase()))\n    .join('');",
    "description": "Creates a string with uppercase characters converted to lowercase and vice versa.\n\n- Use the spread operator (`...`) to convert `str` into an array of characters.\n- Use `String.prototype.toLowerCase()` and `String.prototype.toUpperCase()` to convert lowercase characters to uppercase and vice versa.\n- Use `Array.prototype.map()` to apply the transformation to each character, `Array.prototype.join()` to combine back into a string.\n- Note that it is not necessarily true that `swapCase(swapCase(str)) === str`.",
    "example": "swapCase('Hello world!'); // 'hELLO WORLD!'",
    "id": "swapCase",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const symbolizeKeys = obj =>\n  Object.keys(obj).reduce(\n    (acc, key) => ({ ...acc, [Symbol(key)]: obj[key] }),\n    {}\n  );",
    "description": "Creates a new object, converting each key to a `Symbol`.\n\n- Use `Object.keys()` to get the keys of `obj`.\n- Use `Array.prototype.reduce()` and `Symbol()` to create a new object where each key is converted to a `Symbol`.",
    "example": "symbolizeKeys({ id: 10, name: 'apple' });\n// { [Symbol(id)]: 10, [Symbol(name)]: 'apple' }",
    "id": "symbolizeKeys",
    "tags": [
      "object",
      "advanced"
    ]
  },
  {
    "code": "const symmetricDifference = (a, b) => {\n  const sA = new Set(a),\n    sB = new Set(b);\n  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];\n};",
    "description": "Returns the symmetric difference between two arrays, without filtering out duplicate values.\n\n- Create a `new Set()` from each array to get the unique values of each one.\n- Use `Array.prototype.filter()` on each of them to only keep values not contained in the other.",
    "example": "symmetricDifference([1, 2, 3], [1, 2, 4]); // [3, 4]\nsymmetricDifference([1, 2, 2], [1, 3, 1]); // [2, 2, 3]",
    "id": "symmetricDifference",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const symmetricDifferenceBy = (a, b, fn) => {\n  const sA = new Set(a.map(v => fn(v))),\n    sB = new Set(b.map(v => fn(v)));\n  return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))];\n};",
    "description": "Returns the symmetric difference between two arrays, after applying the provided function to each array element of both.\n\n- Create a `new Set()` from each array to get the unique values of each one after applying `fn` to them.\n- Use `Array.prototype.filter()` on each of them to only keep values not contained in the other.",
    "example": "symmetricDifferenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [ 1.2, 3.4 ]\nsymmetricDifferenceBy(\n  [{ id: 1 }, { id: 2 }, { id: 3 }],\n  [{ id: 1 }, { id: 2 }, { id: 4 }],\n  i => i.id\n);\n// [{ id: 3 }, { id: 4 }]",
    "id": "symmetricDifferenceBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const symmetricDifferenceWith = (arr, val, comp) => [\n  ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1),\n  ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1)\n];",
    "description": "Returns the symmetric difference between two arrays, using a provided function as a comparator.\n\n- Use `Array.prototype.filter()` and `Array.prototype.findIndex()` to find the appropriate values.",
    "example": "symmetricDifferenceWith(\n  [1, 1.2, 1.5, 3, 0],\n  [1.9, 3, 0, 3.9],\n  (a, b) => Math.round(a) === Math.round(b)\n); // [1, 1.2, 3.9]",
    "id": "symmetricDifferenceWith",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);",
    "description": "Returns all elements in an array except for the first one.\n\n- Return `Array.prototype.slice(1)` if `Array.prototype.length` is more than `1`, otherwise, return the whole array.",
    "example": "tail([1, 2, 3]); // [2, 3]\ntail([1]); // [1]",
    "id": "tail",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const take = (arr, n = 1) => arr.slice(0, n);",
    "description": "Creates an array with `n` elements removed from the beginning.\n\n- Use `Array.prototype.slice()` to create a slice of the array with `n` elements taken from the beginning.",
    "example": "take([1, 2, 3], 5); // [1, 2, 3]\ntake([1, 2, 3], 0); // []",
    "id": "take",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);",
    "description": "Creates an array with `n` elements removed from the end.\n\n- Use `Array.prototype.slice()` to create a slice of the array with `n` elements taken from the end.",
    "example": "takeRight([1, 2, 3], 2); // [ 2, 3 ]\ntakeRight([1, 2, 3]); // [3]",
    "id": "takeRight",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const takeRightUntil = (arr, fn) => {\n  for (const [i, val] of [...arr].reverse().entries())\n    if (fn(val)) return i === 0 ? [] : arr.slice(-i);\n  return arr;\n};",
    "description": "Removes elements from the end of an array until the passed function returns `true`.\nReturns the removed elements.\n\n- Create a reversed copy of the array, using the spread operator (`...`) and `Array.prototype.reverse()`.\n- Loop through the reversed copy, using a `for...of` loop over `Array.prototype.entries()` until the returned value from the function is truthy.\n- Return the removed elements, using `Array.prototype.slice()`.\n- The callback function, `fn`, accepts a single argument which is the value of the element.",
    "example": "takeRightUntil([1, 2, 3, 4], n => n < 3); // [3, 4]",
    "id": "takeRightUntil",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const takeRightWhile = (arr, fn) => {\n  for (const [i, val] of [...arr].reverse().entries())\n    if (!fn(val)) return i === 0 ? [] : arr.slice(-i);\n  return arr;\n};",
    "description": "Removes elements from the end of an array until the passed function returns `false`.\nReturns the removed elements.\n\n- Create a reversed copy of the array, using the spread operator (`...`) and `Array.prototype.reverse()`.\n- Loop through the reversed copy, using a `for...of` loop over `Array.prototype.entries()` until the returned value from the function is falsy.\n- Return the removed elements, using `Array.prototype.slice()`.\n- The callback function, `fn`, accepts a single argument which is the value of the element.",
    "example": "takeRightWhile([1, 2, 3, 4], n => n >= 3); // [3, 4]",
    "id": "takeRightWhile",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const takeUntil = (arr, fn) => {\n  for (const [i, val] of arr.entries()) if (fn(val)) return arr.slice(0, i);\n  return arr;\n};",
    "description": "Removes elements in an array until the passed function returns `true`.\nReturns the removed elements.\n\n- Loop through the array, using a `for...of` loop over `Array.prototype.entries()` until the returned value from the function is truthy.\n- Return the removed elements, using `Array.prototype.slice()`.\n- The callback function, `fn`, accepts a single argument which is the value of the element.",
    "example": "takeUntil([1, 2, 3, 4], n => n >= 3); // [1, 2]",
    "id": "takeUntil",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const takeWhile = (arr, fn) => {\n  for (const [i, val] of arr.entries()) if (!fn(val)) return arr.slice(0, i);\n  return arr;\n};",
    "description": "Removes elements in an array until the passed function returns `false`.\nReturns the removed elements.\n\n- Loop through the array, using a `for...of` loop over `Array.prototype.entries()` until the returned value from the function is falsy.\n- Return the removed elements, using `Array.prototype.slice()`.\n- The callback function, `fn`, accepts a single argument which is the value of the element.",
    "example": "takeWhile([1, 2, 3, 4], n => n < 3); // [1, 2]",
    "id": "takeWhile",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const throttle = (fn, wait) => {\n  let inThrottle, lastFn, lastTime;\n  return function() {\n    const context = this,\n      args = arguments;\n    if (!inThrottle) {\n      fn.apply(context, args);\n      lastTime = Date.now();\n      inThrottle = true;\n    } else {\n      clearTimeout(lastFn);\n      lastFn = setTimeout(function() {\n        if (Date.now() - lastTime >= wait) {\n          fn.apply(context, args);\n          lastTime = Date.now();\n        }\n      }, Math.max(wait - (Date.now() - lastTime), 0));\n    }\n  };\n};",
    "description": "Creates a throttled function that only invokes the provided function at most once per every `wait` milliseconds\n\n- Use `setTimeout()` and `clearTimeout()` to throttle the given method, `fn`.\n- Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary `arguments`.\n- Use `Date.now()` to keep track of the last time the throttled function was invoked.\n- Use a variable, `inThrottle`, to prevent a race condition between the first execution of `fn` and the next loop.\n- Omit the second argument, `wait`, to set the timeout at a default of `0` ms.",
    "example": "window.addEventListener(\n  'resize',\n  throttle(function(evt) {\n    console.log(window.innerWidth);\n    console.log(window.innerHeight);\n  }, 250)\n); // Will log the window dimensions at most every 250ms",
    "id": "throttle",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const timeTaken = callback => {\n  console.time('timeTaken');\n  const r = callback();\n  console.timeEnd('timeTaken');\n  return r;\n};",
    "description": "Measures the time it takes for a function to execute.\n\n- Use `Console.time()` and `Console.timeEnd()` to measure the difference between the start and end times to determine how long the callback took to execute.",
    "example": "timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms",
    "id": "timeTaken",
    "tags": [
      "function",
      "beginner"
    ]
  },
  {
    "code": "const times = (n, fn, context = undefined) => {\n  let i = 0;\n  while (fn.call(context, i) !== false && ++i < n) {}\n};",
    "description": "Iterates over a callback `n` times\n\n- Use `Function.prototype.call()` to call `fn` `n` times or until it returns `false`.\n- Omit the last argument, `context`, to use an `undefined` object (or the global object in non-strict mode).",
    "example": "var output = '';\ntimes(5, i => (output += i));\nconsole.log(output); // 01234",
    "id": "times",
    "tags": [
      "function",
      "intermediate"
    ]
  },
  {
    "code": "const toCamelCase = str => {\n  const s =\n    str &&\n    str\n      .match(\n        /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g\n      )\n      .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())\n      .join('');\n  return s.slice(0, 1).toLowerCase() + s.slice(1);\n};",
    "description": "Converts a string to camelcase.\n\n- Use `String.prototype.match()` to break the string into words using an appropriate regexp.\n- Use `Array.prototype.map()`, `Array.prototype.slice()`, `Array.prototype.join()`, `String.prototype.toLowerCase()` and `String.prototype.toUpperCase()` to combine them, capitalizing the first letter of each one.",
    "example": "toCamelCase('some_database_field_name'); // 'someDatabaseFieldName'\ntoCamelCase('Some label that needs to be camelized');\n// 'someLabelThatNeedsToBeCamelized'\ntoCamelCase('some-javascript-property'); // 'someJavascriptProperty'\ntoCamelCase('some-mixed_string with spaces_underscores-and-hyphens');\n// 'someMixedStringWithSpacesUnderscoresAndHyphens'",
    "id": "toCamelCase",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const toCharArray = s => [...s];",
    "description": "Converts a string to an array of characters.\n\n- Use the spread operator (`...`) to convert the string into an array of characters.",
    "example": "toCharArray('hello'); // ['h', 'e', 'l', 'l', 'o']",
    "id": "toCharArray",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const toCurrency = (n, curr, LanguageFormat = undefined) =>\n  Intl.NumberFormat(LanguageFormat, {\n    style: 'currency',\n    currency: curr,\n  }).format(n);",
    "description": "Takes a number and returns it in the specified currency formatting.\n\n- Use `Intl.NumberFormat` to enable country / currency sensitive formatting.",
    "example": "toCurrency(123456.789, 'EUR');\n// €123,456.79  | currency: Euro | currencyLangFormat: Local\ntoCurrency(123456.789, 'USD', 'en-us');\n// $123,456.79  | currency: US Dollar | currencyLangFormat: English (United States)\ntoCurrency(123456.789, 'USD', 'fa');\n// ۱۲۳٬۴۵۶٫۷۹ ؜$ | currency: US Dollar | currencyLangFormat: Farsi\ntoCurrency(322342436423.2435, 'JPY');\n// ¥322,342,436,423 | currency: Japanese Yen | currencyLangFormat: Local\ntoCurrency(322342436423.2435, 'JPY', 'fi');\n// 322 342 436 423 ¥ | currency: Japanese Yen | currencyLangFormat: Finnish",
    "id": "toCurrency",
    "tags": [
      "math",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const toDecimalMark = num => num.toLocaleString('en-US');",
    "description": "Converts a number to a decimal mark formatted string.\n\n- Use `Number.prototype.toLocaleString()` to convert the number to decimal mark format.",
    "example": "toDecimalMark(12305030388.9087); // '12,305,030,388.909'",
    "id": "toDecimalMark",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const toHSLArray = hslStr => hslStr.match(/\\d+/g).map(Number);",
    "description": "Converts an `hsl()` color string to an array of values.\n\n- Use `String.prototype.match()` to get an array of 3 string with the numeric values.\n- Use `Array.prototype.map()` in combination with `Number` to convert them into an array of numeric values.",
    "example": "toHSLArray('hsl(50, 10%, 10%)'); // [50, 10, 10]",
    "id": "toHSLArray",
    "tags": [
      "string",
      "browser",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const toHSLObject = hslStr => {\n  const [hue, saturation, lightness] = hslStr.match(/\\d+/g).map(Number);\n  return { hue, saturation, lightness };\n};",
    "description": "Converts an `hsl()` color string to an object with the values of each color.\n\n- Use `String.prototype.match()` to get an array of 3 string with the numeric values.\n- Use `Array.prototype.map()` in combination with `Number` to convert them into an array of numeric values.\n- Use array destructuring to store the values into named variables and create an appropriate object from them.",
    "example": "toHSLObject('hsl(50, 10%, 10%)'); // { hue: 50, saturation: 10, lightness: 10 }",
    "id": "toHSLObject",
    "tags": [
      "string",
      "browser",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const toHash = (object, key) =>\n  Array.prototype.reduce.call(\n    object,\n    (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc),\n    {}\n  );",
    "description": "Reduces a given array-like into a value hash (keyed data store).\n\n- Given an iterable object or array-like structure, call `Array.prototype.reduce.call()` on the provided object to step over it and return an `Object`, keyed by the reference value.",
    "example": "toHash([4, 3, 2, 1]); // { 0: 4, 1: 3, 2: 2, 3: 1 }\ntoHash([{ a: 'label' }], 'a'); // { label: { a: 'label' } }\n// A more in depth example:\nlet users = [\n  { id: 1, first: 'Jon' },\n  { id: 2, first: 'Joe' },\n  { id: 3, first: 'Moe' },\n];\nlet managers = [{ manager: 1, employees: [2, 3] }];\n// We use function here because we want a bindable reference, \n// but a closure referencing the hash would work, too.\nmanagers.forEach(\n  manager =>\n    (manager.employees = manager.employees.map(function(id) {\n      return this[id];\n    }, toHash(users, 'id')))\n);\nmanagers; \n// [ {manager:1, employees: [ {id: 2, first: 'Joe'}, {id: 3, first: 'Moe'} ] } ]",
    "id": "toHash",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const toISOStringWithTimezone = date => {\n  const tzOffset = -date.getTimezoneOffset();\n  const diff = tzOffset >= 0 ? '+' : '-';\n  const pad = n => \\`\\${Math.floor(Math.abs(n))}\\`.padStart(2, '0');\n  return date.getFullYear() +\n    '-' + pad(date.getMonth() + 1) +\n    '-' + pad(date.getDate()) +\n    'T' + pad(date.getHours()) +\n    ':' + pad(date.getMinutes()) +\n    ':' + pad(date.getSeconds()) +\n    diff + pad(tzOffset / 60) +\n    ':' + pad(tzOffset % 60);\n};",
    "description": "Converts a date to extended ISO format (ISO 8601), including timezone offset.\n\n- Use `Date.prototype.getTimezoneOffset()` to get the timezone offset and reverse it. Store its sign in `diff`.\n- Define a helper function, `pad`, that normalizes any passed number to an integer using `Math.floor()` and `Math.abs()` and pads it to `2` digits, using `String.prototype.padStart()`.\n- Use `pad()` and the built-in methods in the `Date` prototype to build the ISO 8601 string with timezone offset.",
    "example": "toISOStringWithTimezone(new Date()); // '2020-10-06T20:43:33-04:00'",
    "id": "toISOStringWithTimezone",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const toKebabCase = str =>\n  str &&\n  str\n    .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)\n    .map(x => x.toLowerCase())\n    .join('-');",
    "description": "Converts a string to kebab case.\n\n- Use `String.prototype.match()` to break the string into words using an appropriate regexp.\n- Use `Array.prototype.map()`, `Array.prototype.join()` and `String.prototype.toLowerCase()` to combine them, adding `-` as a separator.",
    "example": "toKebabCase('camelCase'); // 'camel-case'\ntoKebabCase('some text'); // 'some-text'\ntoKebabCase('some-mixed_string With spaces_underscores-and-hyphens');\n// 'some-mixed-string-with-spaces-underscores-and-hyphens'\ntoKebabCase('AllThe-small Things'); // 'all-the-small-things'\ntoKebabCase('IAmEditingSomeXMLAndHTML');\n// 'i-am-editing-some-xml-and-html'",
    "id": "toKebabCase",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const toOrdinalSuffix = num => {\n  const int = parseInt(num),\n    digits = [int % 10, int % 100],\n    ordinals = ['st', 'nd', 'rd', 'th'],\n    oPattern = [1, 2, 3, 4],\n    tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];\n  return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])\n    ? int + ordinals[digits[0] - 1]\n    : int + ordinals[3];\n};",
    "description": "Takes a number and returns it as a string with the correct ordinal indicator suffix.\n\n- Use the modulo operator (`%`) to find values of single and tens digits.\n- Find which ordinal pattern digits match.\n- If digit is found in teens pattern, use teens ordinal.",
    "example": "toOrdinalSuffix('123'); // '123rd'",
    "id": "toOrdinalSuffix",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const toPairs = obj =>\n  obj[Symbol.iterator] instanceof Function && obj.entries instanceof Function\n    ? Array.from(obj.entries())\n    : Object.entries(obj);",
    "description": "Creates an array of key-value pair arrays from an object or other iterable.\n\n- Check if `Symbol.iterator` is defined and, if so, use `Array.prototype.entries()` to get an iterator for the given iterable.\n- Use `Array.from()` to convert the result to an array of key-value pair arrays.\n- If `Symbol.iterator` is not defined for `obj`, use `Object.entries()` instead.",
    "example": "toPairs({ a: 1, b: 2 }); // [['a', 1], ['b', 2]]\ntoPairs([2, 4, 8]); // [[0, 2], [1, 4], [2, 8]]\ntoPairs('shy'); // [['0', 's'], ['1', 'h'], ['2', 'y']]\ntoPairs(new Set(['a', 'b', 'c', 'a'])); // [['a', 'a'], ['b', 'b'], ['c', 'c']]",
    "id": "toPairs",
    "tags": [
      "object",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const toPascalCase = str =>\r\n  str\r\n    .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)\r\n    .map(x => x.charAt(0).toUpperCase() + x.slice(1).toLowerCase())\r\n    .join('');",
    "description": "Converts a string to pascal case.\r\n\r\n- Use `String.prototype.match()` to break the string into words using an appropriate regexp.\r\n- Use `Array.prototype.map()`, `Array.prototype.slice()`, `Array.prototype.join()`, `String.prototype.toUpperCase()` and `String.prototype.toLowerCase()` to combine them, capitalizing the first letter of each word and lowercasing the rest.",
    "example": "toPascalCase('some_database_field_name'); // 'SomeDatabaseFieldName'\r\ntoPascalCase('Some label that needs to be pascalized');\r\n// 'SomeLabelThatNeedsToBePascalized'\r\ntoPascalCase('some-javascript-property'); // 'SomeJavascriptProperty'\r\ntoPascalCase('some-mixed_string with spaces_underscores-and-hyphens');\r\n// 'SomeMixedStringWithSpacesUnderscoresAndHyphens'",
    "id": "toPascalCase\r",
    "tags": [
      "string",
      "regexp",
      "intermediate\r"
    ]
  },
  {
    "code": "const toRGBArray = rgbStr => rgbStr.match(/\\d+/g).map(Number);",
    "description": "Converts an `rgb()` color string to an array of values.\n\n- Use `String.prototype.match()` to get an array of 3 string with the numeric values.\n- Use `Array.prototype.map()` in combination with `Number` to convert them into an array of numeric values.",
    "example": "toRGBArray('rgb(255, 12, 0)'); // [255, 12, 0]",
    "id": "toRGBArray",
    "tags": [
      "string",
      "browser",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const toRGBObject = rgbStr => {\n  const [red, green, blue] = rgbStr.match(/\\d+/g).map(Number);\n  return { red, green, blue };\n};",
    "description": "Converts an `rgb()` color string to an object with the values of each color.\n\n- Use `String.prototype.match()` to get an array of 3 string with the numeric values.\n- Use `Array.prototype.map()` in combination with `Number` to convert them into an array of numeric values.\n- Use array destructuring to store the values into named variables and create an appropriate object from them.",
    "example": "toRGBObject('rgb(255, 12, 0)'); // {red: 255, green: 12, blue: 0}",
    "id": "toRGBObject",
    "tags": [
      "string",
      "browser",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const toRomanNumeral = num => {\n  const lookup = [\n    ['M', 1000],\n    ['CM', 900],\n    ['D', 500],\n    ['CD', 400],\n    ['C', 100],\n    ['XC', 90],\n    ['L', 50],\n    ['XL', 40],\n    ['X', 10],\n    ['IX', 9],\n    ['V', 5],\n    ['IV', 4],\n    ['I', 1],\n  ];\n  return lookup.reduce((acc, [k, v]) => {\n    acc += k.repeat(Math.floor(num / v));\n    num = num % v;\n    return acc;\n  }, '');\n};",
    "description": "Converts an integer to its roman numeral representation.\nAccepts value between `1` and `3999` (both inclusive).\n\n- Create a lookup table containing 2-value arrays in the form of (roman value, integer).\n- Use `Array.prototype.reduce()` to loop over the values in `lookup` and repeatedly divide `num` by the value.\n- Use `String.prototype.repeat()` to add the roman numeral representation to the accumulator.",
    "example": "toRomanNumeral(3); // 'III'\ntoRomanNumeral(11); // 'XI'\ntoRomanNumeral(1998); // 'MCMXCVIII'",
    "id": "toRomanNumeral",
    "tags": [
      "math",
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const toSafeInteger = num =>\n  Math.round(\n    Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)\n  );",
    "description": "Converts a value to a safe integer.\n\n- Use `Math.max()` and `Math.min()` to find the closest safe value.\n- Use `Math.round()` to convert to an integer.",
    "example": "toSafeInteger('3.2'); // 3\ntoSafeInteger(Infinity); // 9007199254740991",
    "id": "toSafeInteger",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const toSnakeCase = str =>\n  str &&\n  str\n    .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)\n    .map(x => x.toLowerCase())\n    .join('_');",
    "description": "Converts a string to snake case.\n\n- Use `String.prototype.match()` to break the string into words using an appropriate regexp.\n- Use `Array.prototype.map()`, `Array.prototype.slice()`, `Array.prototype.join()` and `String.prototype.toLowerCase()` to combine them, adding `_` as a separator.",
    "example": "toSnakeCase('camelCase'); // 'camel_case'\ntoSnakeCase('some text'); // 'some_text'\ntoSnakeCase('some-mixed_string With spaces_underscores-and-hyphens');\n// 'some_mixed_string_with_spaces_underscores_and_hyphens'\ntoSnakeCase('AllThe-small Things'); // 'all_the_small_things'\ntoSnakeCase('IAmEditingSomeXMLAndHTML');\n// 'i_am_editing_some_xml_and_html'",
    "id": "toSnakeCase",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const toTitleCase = str =>\n  str\n    .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)\n    .map(x => x.charAt(0).toUpperCase() + x.slice(1))\n    .join(' ');",
    "description": "Converts a string to title case.\n\n- Use `String.prototype.match()` to break the string into words using an appropriate regexp.\n- Use `Array.prototype.map()`, `Array.prototype.slice()`, `Array.prototype.join()` and `String.prototype.toUpperCase()` to combine them, capitalizing the first letter of each word and adding a whitespace between them.",
    "example": "toTitleCase('some_database_field_name'); // 'Some Database Field Name'\ntoTitleCase('Some label that needs to be title-cased');\n// 'Some Label That Needs To Be Title Cased'\ntoTitleCase('some-package-name'); // 'Some Package Name'\ntoTitleCase('some-mixed_string with spaces_underscores-and-hyphens');\n// 'Some Mixed String With Spaces Underscores And Hyphens'",
    "id": "toTitleCase",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const toggleClass = (el, className) => el.classList.toggle(className);",
    "description": "Toggles a class for an HTML element.\n\n- Use `Element.classList` and `DOMTokenList.toggle()` to toggle the specified class for the element.",
    "example": "toggleClass(document.querySelector('p.special'), 'special');\n// The paragraph will not have the 'special' class anymore",
    "id": "toggleClass",
    "tags": [
      "browser",
      "beginner"
    ]
  },
  {
    "code": "const tomorrow = () => {\n  let d = new Date();\n  d.setDate(d.getDate() + 1);\n  return d.toISOString().split('T')[0];\n};",
    "description": "Results in a string representation of tomorrow's date.\n\n- Use `new Date()` to get the current date.\n- Increment it by one using `Date.prototype.getDate()` and set the value to the result using `Date.prototype.setDate()`.\n- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.",
    "example": "tomorrow(); // 2018-10-19 (if current date is 2018-10-18)",
    "id": "tomorrow",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const transform = (obj, fn, acc) =>\n  Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);",
    "description": "Applies a function against an accumulator and each key in the object (from left to right).\n\n- Use `Object.keys()` to iterate over each key in the object.\n- Use `Array.prototype.reduce()` to apply the specified function against the given accumulator.",
    "example": "transform(\n  { a: 1, b: 2, c: 1 },\n  (r, v, k) => {\n    (r[v] || (r[v] = [])).push(k);\n    return r;\n  },\n  {}\n); // { '1': ['a', 'c'], '2': ['b'] }",
    "id": "transform",
    "tags": [
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const triggerEvent = (el, eventType, detail) =>\n  el.dispatchEvent(new CustomEvent(eventType, { detail }));",
    "description": "Triggers a specific event on a given element, optionally passing custom data.\n\n- Use `new CustomEvent()` to create an event from the specified `eventType` and details.\n- Use `EventTarget.dispatchEvent()` to trigger the newly created event on the given element.\n- Omit the third argument, `detail`, if you do not want to pass custom data to the triggered event.",
    "example": "triggerEvent(document.getElementById('myId'), 'click');\ntriggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });",
    "id": "triggerEvent",
    "tags": [
      "browser",
      "event",
      "intermediate"
    ]
  },
  {
    "code": "const truncateString = (str, num) =>\n  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;",
    "description": "Truncates a string up to a specified length.\n\n- Determine if `String.prototype.length` is greater than `num`.\n- Return the string truncated to the desired length, with `'...'` appended to the end or the original string.",
    "example": "truncateString('boomerang', 7); // 'boom...'",
    "id": "truncateString",
    "tags": [
      "string",
      "beginner"
    ]
  },
  {
    "code": "const truncateStringAtWhitespace = (str, lim, ending = '...') => {\n  if (str.length <= lim) return str;\n  const lastSpace = str.slice(0, lim - ending.length + 1).lastIndexOf(' ');\n  return str.slice(0, lastSpace > 0 ? lastSpace : lim - ending.length) + ending;\n};",
    "description": "Truncates a string up to specified length, respecting whitespace when possible.\n\n- Determine if `String.prototype.length` is greater or equal to `lim`. If not, return it as-is.\n- Use `String.prototype.slice()` and `String.prototype.lastIndexOf()` to find the index of the last space below the desired `lim`.\n- Use `String.prototype.slice()` to appropriately truncate `str` based on `lastSpace`, respecting whitespace if possible and appending `ending` at the end.\n- Omit the third argument, `ending`, to use the default ending of `'...'`.",
    "example": "truncateStringAtWhitespace('short', 10); // 'short'\ntruncateStringAtWhitespace('not so short', 10); // 'not so...'\ntruncateStringAtWhitespace('trying a thing', 10); // 'trying...'\ntruncateStringAtWhitespace('javascripting', 10); // 'javascr...'",
    "id": "truncateStringAtWhitespace",
    "tags": [
      "string",
      "intermediate"
    ]
  },
  {
    "code": "const truthCheckCollection = (collection, pre) =>\n  collection.every(obj => obj[pre]);",
    "description": "Checks if the predicate function is truthy for all elements of a collection.\n\n- Use `Array.prototype.every()` to check if each passed object has the specified property and if it returns a truthy value.",
    "example": "truthCheckCollection(\n  [\n    { user: 'Tinky-Winky', sex: 'male' },\n    { user: 'Dipsy', sex: 'male' },\n  ],\n  'sex'\n); // true",
    "id": "truthCheckCollection",
    "tags": [
      "object",
      "logic",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const unary = fn => val => fn(val);",
    "description": "Creates a function that accepts up to one argument, ignoring any additional arguments.\n\n- Call the provided function, `fn`, with just the first argument supplied.",
    "example": "['6', '8', '10'].map(unary(parseInt)); // [6, 8, 10]",
    "id": "unary",
    "tags": [
      "function",
      "beginner"
    ]
  },
  {
    "code": "const uncurry = (fn, n = 1) => (...args) => {\n  const next = acc => args => args.reduce((x, y) => x(y), acc);\n  if (n > args.length) throw new RangeError('Arguments too few!');\n  return next(fn)(args.slice(0, n));\n};",
    "description": "Uncurries a function up to depth `n`.\n\n- Return a variadic function.\n- Use `Array.prototype.reduce()` on the provided arguments to call each subsequent curry level of the function.\n- If the `length` of the provided arguments is less than `n` throw an error.\n- Otherwise, call `fn` with the proper amount of arguments, using `Array.prototype.slice(0, n)`.\n- Omit the second argument, `n`, to uncurry up to depth `1`.",
    "example": "const add = x => y => z => x + y + z;\nconst uncurriedAdd = uncurry(add, 3);\nuncurriedAdd(1, 2, 3); // 6",
    "id": "uncurry",
    "tags": [
      "function",
      "advanced"
    ]
  },
  {
    "code": "const unescapeHTML = str =>\n  str.replace(\n    /&amp;|&lt;|&gt;|&#39;|&quot;/g,\n    tag =>\n      ({\n        '&amp;': '&',\n        '&lt;': '<',\n        '&gt;': '>',\n        '&#39;': \"'\",\n        '&quot;': '\"'\n      }[tag] || tag)\n  );",
    "description": "Unescapes escaped HTML characters.\n\n- Use `String.prototype.replace()` with a regexp that matches the characters that need to be unescaped.\n- Use the function's callback to replace each escaped character instance with its associated unescaped character using a dictionary (object).",
    "example": "unescapeHTML('&lt;a href=&quot;#&quot;&gt;Me &amp; you&lt;/a&gt;');\n// '<a href=\"#\">Me & you</a>'",
    "id": "unescapeHTML",
    "tags": [
      "string",
      "browser",
      "regexp",
      "beginner"
    ]
  },
  {
    "code": "const unflattenObject = obj =>\n  Object.keys(obj).reduce((res, k) => {\n    k.split('.').reduce(\n      (acc, e, i, keys) =>\n        acc[e] ||\n        (acc[e] = isNaN(Number(keys[i + 1]))\n          ? keys.length - 1 === i\n            ? obj[k]\n            : {}\n          : []),\n      res\n    );\n    return res;\n  }, {});",
    "description": "Unflatten an object with the paths for keys.\n\n- Use nested `Array.prototype.reduce()` to convert the flat path to a leaf node.\n- Use `String.prototype.split('.')` to split each key with a dot delimiter and `Array.prototype.reduce()` to add objects against the keys.\n- If the current accumulator already contains a value against a particular key, return its value as the next accumulator.\n- Otherwise, add the appropriate key-value pair to the accumulator object and return the value as the accumulator.",
    "example": "unflattenObject({ 'a.b.c': 1, d: 1 }); // { a: { b: { c: 1 } }, d: 1 }\nunflattenObject({ 'a.b': 1, 'a.c': 2, d: 3 }); // { a: { b: 1, c: 2 }, d: 3 }\nunflattenObject({ 'a.b.0': 8, d: 3 }); // { a: { b: [ 8 ] }, d: 3 }",
    "id": "unflattenObject",
    "tags": [
      "object",
      "advanced"
    ]
  },
  {
    "code": "const unfold = (fn, seed) => {\n  let result = [],\n    val = [null, seed];\n  while ((val = fn(val[1]))) result.push(val[0]);\n  return result;\n};",
    "description": "Builds an array, using an iterator function and an initial seed value.\n\n- Use a `while` loop and `Array.prototype.push()` to call the function repeatedly until it returns `false`.\n- The iterator function accepts one argument (`seed`) and must always return an array with two elements ([`value`, `nextSeed`]) or `false` to terminate.",
    "example": "var f = n => (n > 50 ? false : [-n, n + 10]);\nunfold(f, 10); // [-10, -20, -30, -40, -50]",
    "id": "unfold",
    "tags": [
      "function",
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const union = (a, b) => Array.from(new Set([...a, ...b]));",
    "description": "Returns every element that exists in any of the two arrays at least once.\n\n- Create a `new Set()` with all values of `a` and `b` and convert it to an array.",
    "example": "union([1, 2, 3], [4, 3, 2]); // [1, 2, 3, 4]",
    "id": "union",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const unionBy = (a, b, fn) => {\n  const s = new Set(a.map(fn));\n  return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))]));\n};",
    "description": "Returns every element that exists in any of the two arrays at least once, after applying the provided function to each array element of both.\n\n- Create a `new Set()` by applying all `fn` to all values of `a`.\n- Create a `new Set()` from `a` and all elements in `b` whose value, after applying `fn` does not match a value in the previously created set.\n- Return the last set converted to an array.",
    "example": "unionBy([2.1], [1.2, 2.3], Math.floor); // [2.1, 1.2]\nunionBy([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], x => x.id)\n// [{ id: 1 }, { id: 2 }, { id: 3 }]",
    "id": "unionBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const unionWith = (a, b, comp) =>\n  Array.from(\n    new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])\n  );",
    "description": "Returns every element that exists in any of the two arrays at least once, using a provided comparator function.\n\n- Create a `new Set()` with all values of `a` and values in `b` for which the comparator finds no matches in `a`, using `Array.prototype.findIndex()`.",
    "example": "unionWith(\n  [1, 1.2, 1.5, 3, 0],\n  [1.9, 3, 0, 3.9],\n  (a, b) => Math.round(a) === Math.round(b)\n);\n// [1, 1.2, 1.5, 3, 0, 3.9]",
    "id": "unionWith",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const uniqueElements = arr => [...new Set(arr)];",
    "description": "Finds all unique values in an array.\n\n- Create a `new Set()` from the given array to discard duplicated values.\n- Use the spread operator (`...`) to convert it back to an array.",
    "example": "uniqueElements([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5]",
    "id": "uniqueElements",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const uniqueElementsBy = (arr, fn) =>\n  arr.reduce((acc, v) => {\n    if (!acc.some(x => fn(v, x))) acc.push(v);\n    return acc;\n  }, []);",
    "description": "Finds all unique values of an array, based on a provided comparator function.\n\n- Use `Array.prototype.reduce()` and `Array.prototype.some()` to create an array containing only the first unique occurrence of each value, based on the comparator function, `fn`.\n- The comparator function takes two arguments: the values of the two elements being compared.",
    "example": "uniqueElementsBy(\n  [\n    { id: 0, value: 'a' },\n    { id: 1, value: 'b' },\n    { id: 2, value: 'c' },\n    { id: 1, value: 'd' },\n    { id: 0, value: 'e' }\n  ],\n  (a, b) => a.id == b.id\n); // [ { id: 0, value: 'a' }, { id: 1, value: 'b' }, { id: 2, value: 'c' } ]",
    "id": "uniqueElementsBy",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const uniqueElementsByRight = (arr, fn) =>\n  arr.reduceRight((acc, v) => {\n    if (!acc.some(x => fn(v, x))) acc.push(v);\n    return acc;\n  }, []);",
    "description": "Finds all unique values of an array, based on a provided comparator function, starting from the right.\n\n- Use `Array.prototype.reduceRight()` and `Array.prototype.some()` to create an array containing only the last unique occurrence of each value, based on the comparator function, `fn`.\n- The comparator function takes two arguments: the values of the two elements being compared.",
    "example": "uniqueElementsByRight(\n  [\n    { id: 0, value: 'a' },\n    { id: 1, value: 'b' },\n    { id: 2, value: 'c' },\n    { id: 1, value: 'd' },\n    { id: 0, value: 'e' }\n  ],\n  (a, b) => a.id == b.id\n); // [ { id: 0, value: 'e' }, { id: 1, value: 'd' }, { id: 2, value: 'c' } ]",
    "id": "uniqueElementsByRight",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const uniqueSymmetricDifference = (a, b) => [\n  ...new Set([\n    ...a.filter(v => !b.includes(v)),\n    ...b.filter(v => !a.includes(v)),\n  ]),\n];",
    "description": "Returns the unique symmetric difference between two arrays, not containing duplicate values from either array.\n\n- Use `Array.prototype.filter()` and `Array.prototype.includes()` on each array to remove values contained in the other.\n- Create a `new Set()` from the results, removing duplicate values.",
    "example": "uniqueSymmetricDifference([1, 2, 3], [1, 2, 4]); // [3, 4]\nuniqueSymmetricDifference([1, 2, 2], [1, 3, 1]); // [2, 3]",
    "id": "uniqueSymmetricDifference",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const untildify = str =>\n  str.replace(/^~($|\\/|\\\\)/, \\`\\${require('os').homedir()}$1\\`);",
    "description": "Converts a tilde path to an absolute path.\n\n- Use `String.prototype.replace()` with a regular expression and `os.homedir()` to replace the `~` in the start of the path with the home directory.",
    "example": "untildify('~/node'); // '/Users/aUser/node'",
    "id": "untildify",
    "tags": [
      "node",
      "string",
      "beginner"
    ]
  },
  {
    "code": "const unzip = arr =>\n  arr.reduce(\n    (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),\n    Array.from({\n      length: Math.max(...arr.map(x => x.length))\n    }).map(x => [])\n  );",
    "description": "Creates an array of arrays, ungrouping the elements in an array produced by [zip](/js/s/zip).\n\n- Use `Math.max()`, `Function.prototype.apply()` to get the longest subarray in the array, `Array.prototype.map()` to make each element an array.\n- Use `Array.prototype.reduce()` and `Array.prototype.forEach()` to map grouped values to individual arrays.",
    "example": "unzip([['a', 1, true], ['b', 2, false]]); // [['a', 'b'], [1, 2], [true, false]]\nunzip([['a', 1, true], ['b', 2]]); // [['a', 'b'], [1, 2], [true]]",
    "id": "unzip",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const unzipWith = (arr, fn) =>\n  arr\n    .reduce(\n      (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),\n      Array.from({\n        length: Math.max(...arr.map(x => x.length))\n      }).map(x => [])\n    )\n    .map(val => fn(...val));",
    "description": "Creates an array of elements, ungrouping the elements in an array produced by [zip](/js/s/zip) and applying the provided function.\n\n- Use `Math.max()`, `Function.prototype.apply()` to get the longest subarray in the array, `Array.prototype.map()` to make each element an array.\n- Use `Array.prototype.reduce()` and `Array.prototype.forEach()` to map grouped values to individual arrays.\n- Use `Array.prototype.map()` and the spread operator (`...`) to apply `fn` to each individual group of elements.",
    "example": "unzipWith(\n  [\n    [1, 10, 100],\n    [2, 20, 200],\n  ],\n  (...args) => args.reduce((acc, v) => acc + v, 0)\n);\n// [3, 30, 300]",
    "id": "unzipWith",
    "tags": [
      "array",
      "advanced"
    ]
  },
  {
    "code": "const validateNumber = n => {\n  const num = parseFloat(n);\n  return !Number.isNaN(num) && Number.isFinite(num) && Number(n) == n;\n}",
    "description": "Checks if the given value is a number.\n\n- Use `parseFloat()` to try to convert `n` to a number.\n- Use `!Number.isNaN()` to check if `num` is a number.\n- Use `Number.isFinite()` to check if `num` is finite.\n- Use `Number()` and the loose equality operator (`==`) to check if the coercion holds.",
    "example": "validateNumber('10'); // true\nvalidateNumber('a'); // false",
    "id": "validateNumber",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const vectorAngle = (x, y) => {\n  let mX = Math.sqrt(x.reduce((acc, n) => acc + Math.pow(n, 2), 0));\n  let mY = Math.sqrt(y.reduce((acc, n) => acc + Math.pow(n, 2), 0));\n  return Math.acos(x.reduce((acc, n, i) => acc + n * y[i], 0) / (mX * mY));\n};",
    "description": "Calculates the angle (theta) between two vectors.\n\n- Use `Array.prototype.reduce()`, `Math.pow()` and `Math.sqrt()` to calculate the magnitude of each vector and the scalar product of the two vectors.\n- Use `Math.acos()` to calculate the arccosine and get the theta value.",
    "example": "vectorAngle([3, 4], [4, 3]); // 0.283794109208328",
    "id": "vectorAngle",
    "tags": [
      "math",
      "beginner"
    ]
  },
  {
    "code": "const vectorDistance = (x, y) =>\n  Math.sqrt(x.reduce((acc, val, i) => acc + Math.pow(val - y[i], 2), 0));",
    "description": "Calculates the distance between two vectors.\n\n- Use `Array.prototype.reduce()`, `Math.pow()` and `Math.sqrt()` to calculate the Euclidean distance between two vectors.",
    "example": "vectorDistance([10, 0, 5], [20, 0, 10]); // 11.180339887498949",
    "id": "vectorDistance",
    "tags": [
      "math",
      "algorithm",
      "beginner"
    ]
  },
  {
    "code": "const walkThrough = function* (obj) {\n  const walk = function* (x, previous = []) {\n    for (let key of Object.keys(x)) {\n      if (typeof x[key] === 'object') yield* walk(x[key], [...previous, key]);\n      else yield [[...previous, key], x[key]];\n    }\n  };\n  yield* walk(obj);\n};",
    "description": "Creates a generator, that walks through all the keys of a given object.\n\n- Use recursion.\n- Define a generator function, `walk`, that takes an object and an array of keys.\n- Use a `for...of` loop and `Object.keys()` to iterate over the keys of the object.\n- Use `typeof` to check if each value in the given object is itself an object.\n- If so, use the `yield*` expression to recursively delegate to the same generator function, `walk`, appending the current `key` to the array of keys. Otherwise, `yield` an array of keys representing the current path and the value of the given `key`.\n- Use the `yield*` expression to delegate to the `walk` generator function.",
    "example": "const obj = {\n  a: 10,\n  b: 20,\n  c: {\n    d: 10,\n    e: 20,\n    f: [30, 40]\n  },\n  g: [\n    {\n      h: 10,\n      i: 20\n    },\n    {\n      j: 30\n    },\n    40\n  ]\n};\n[...walkThrough(obj)];\n/*\n[\n  [['a'], 10],\n  [['b'], 20],\n  [['c', 'd'], 10],\n  [['c', 'e'], 20],\n  [['c', 'f', '0'], 30],\n  [['c', 'f', '1'], 40],\n  [['g', '0', 'h'], 10],\n  [['g', '0', 'i'], 20],\n  [['g', '1', 'j'], 30],\n  [['g', '2'], 40]\n]\n*/",
    "id": "walkThrough",
    "tags": [
      "object",
      "recursion",
      "generator",
      "advanced"
    ]
  },
  {
    "code": "const weekOfYear = date => {\n  const startOfYear = new Date(date.getFullYear(), 0, 1);\n  startOfYear.setDate(startOfYear.getDate() + (startOfYear.getDay() % 7));\n  return Math.round((date - startOfYear) / (7 * 24 * 3600 * 1000));\n};",
    "description": "Returns the zero-indexed week of the year that a date corresponds to.\n\n- Use `new Date()` and `Date.prototype.getFullYear()` to get the first day of the year as a `Date` object.\n- Use `Date.prototype.setDate()`, `Date.prototype.getDate()` and `Date.prototype.getDay()` along with the modulo (`%`) operator to get the first Monday of the year.\n- Subtract the first Monday of the year from the given `date` and divide with the number of milliseconds in a week.\n- Use `Math.round()` to get the zero-indexed week of the year corresponding to the given `date`.\n- `-0` is returned if the given `date` is before the first Monday of the year.",
    "example": "weekOfYear(new Date('2021-06-18')); // 23",
    "id": "weekOfYear",
    "tags": [
      "date",
      "advanced"
    ]
  },
  {
    "code": "const weightedAverage = (nums, weights) => {\n  const [sum, weightSum] = weights.reduce(\n    (acc, w, i) => {\n      acc[0] = acc[0] + nums[i] * w;\n      acc[1] = acc[1] + w;\n      return acc;\n    },\n    [0, 0]\n  );\n  return sum / weightSum;\n};",
    "description": "Calculates the weighted average of two or more numbers.\n\n- Use `Array.prototype.reduce()` to create the weighted sum of the values and the sum of the weights.\n- Divide them with each other to get the weighted average.",
    "example": "weightedAverage([1, 2, 3], [0.6, 0.2, 0.3]); // 1.72727",
    "id": "weightedAverage",
    "tags": [
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const weightedSample = (arr, weights) => {\n  let roll = Math.random();\n  return arr[\n    weights\n      .reduce(\n        (acc, w, i) => (i === 0 ? [w] : [...acc, acc[acc.length - 1] + w]),\n        []\n      )\n      .findIndex((v, i, s) => roll >= (i === 0 ? 0 : s[i - 1]) && roll < v)\n  ];\n};",
    "description": "Gets a random element from an array, using the provided `weights` as the probabilities for each element.\n\n- Use `Array.prototype.reduce()` to create an array of partial sums for each value in `weights`.\n- Use `Math.random()` to generate a random number and `Array.prototype.findIndex()` to find the correct index based on the array previously produced.\n- Finally, return the element of `arr` with the produced index.",
    "example": "weightedSample([3, 7, 9, 11], [0.1, 0.2, 0.6, 0.1]); // 9",
    "id": "weightedSample",
    "tags": [
      "array",
      "random",
      "advanced"
    ]
  },
  {
    "code": "const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);",
    "description": "Returns a function that takes one argument and runs a callback if it's truthy or returns it if falsy.\n\n- Return a function expecting a single value, `x`, that returns the appropriate value based on `pred`.",
    "example": "const doubleEvenNumbers = when(x => x % 2 === 0, x => x * 2);\ndoubleEvenNumbers(2); // 4\ndoubleEvenNumbers(1); // 1",
    "id": "when",
    "tags": [
      "function",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const without = (arr, ...args) => arr.filter(v => !args.includes(v));",
    "description": "Filters out the elements of an array that have one of the specified values.\n\n- Use `Array.prototype.includes()` to find values to exclude.\n- Use `Array.prototype.filter()` to create an array excluding them.",
    "example": "without([2, 1, 2, 3], 1, 2); // [3]",
    "id": "without",
    "tags": [
      "array",
      "beginner"
    ]
  },
  {
    "code": "const wordWrap = (str, max, br = '\\n') => str.replace(\n  new RegExp(\\`(?![^\\\\n]{1,\\${max}}$)([^\\\\n]{1,\\${max}})\\\\s\\`, 'g'), '$1' + br\n);",
    "description": "Wraps a string to a given number of characters using a string break character.\n\n- Use `String.prototype.replace()` and a regular expression to insert a given break character at the nearest whitespace of `max` characters.\n- Omit the third argument, `br`, to use the default value of `'\\n'`.",
    "example": "wordWrap(\n  'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tempus.',\n  32\n);\n// 'Lorem ipsum dolor sit amet,\\nconsectetur adipiscing elit.\\nFusce tempus.'\nwordWrap(\n  'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tempus.',\n  32,\n  '\\r\\n'\n);\n// 'Lorem ipsum dolor sit amet,\\r\\nconsectetur adipiscing elit.\\r\\nFusce tempus.'",
    "id": "wordWrap",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const words = (str, pattern = /[^a-zA-Z-]+/) =>\n  str.split(pattern).filter(Boolean);",
    "description": "Converts a given string into an array of words.\n\n- Use `String.prototype.split()` with a supplied `pattern` (defaults to non-alpha as a regexp) to convert to an array of strings.\n- Use `Array.prototype.filter()` to remove any empty strings.\n- Omit the second argument, `pattern`, to use the default regexp.",
    "example": "words('I love javaScript!!'); // ['I', 'love', 'javaScript']\nwords('python, javaScript & coffee'); // ['python', 'javaScript', 'coffee']",
    "id": "words",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const xProd = (a, b) =>\n  a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);",
    "description": "Creates a new array out of the two supplied by creating each possible pair from the arrays.\n\n- Use `Array.prototype.reduce()`, `Array.prototype.map()` and `Array.prototype.concat()` to produce every possible pair from the elements of the two arrays.",
    "example": "xProd([1, 2], ['a', 'b']); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]",
    "id": "xProd",
    "tags": [
      "array",
      "math",
      "intermediate"
    ]
  },
  {
    "code": "const xor = (a, b) => (( a || b ) && !( a && b ));",
    "description": "Checks if only one of the arguments is `true`.\n\n- Use the logical or (`||`), and (`&&`) and not (`!`) operators on the two given values to create the logical xor.",
    "example": "xor(true, true); // false\nxor(true, false); // true\nxor(false, true); // true\nxor(false, false); // false",
    "id": "xor",
    "tags": [
      "math",
      "logic",
      "beginner"
    ]
  },
  {
    "code": "const yesNo = (val, def = false) =>\n  /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;",
    "description": "Returns `true` if the string is `y`/`yes` or `false` if the string is `n`/`no`.\n\n- Use `RegExp.prototype.test()` to check if the string evaluates to `y/yes` or `n/no`.\n- Omit the second argument, `def` to set the default answer as `no`.",
    "example": "yesNo('Y'); // true\nyesNo('yes'); // true\nyesNo('No'); // false\nyesNo('Foo', true); // true",
    "id": "yesNo",
    "tags": [
      "string",
      "regexp",
      "intermediate"
    ]
  },
  {
    "code": "const yesterday = () => {\n  let d = new Date();\n  d.setDate(d.getDate() - 1);\n  return d.toISOString().split('T')[0];\n};",
    "description": "Results in a string representation of yesterday's date.\n\n- Use `new Date()` to get the current date.\n- Decrement it by one using `Date.prototype.getDate()` and set the value to the result using `Date.prototype.setDate()`.\n- Use `Date.prototype.toISOString()` to return a string in `yyyy-mm-dd` format.",
    "example": "yesterday(); // 2018-10-17 (if current date is 2018-10-18)",
    "id": "yesterday",
    "tags": [
      "date",
      "intermediate"
    ]
  },
  {
    "code": "const zip = (...arrays) => {\n  const maxLength = Math.max(...arrays.map(x => x.length));\n  return Array.from({ length: maxLength }).map((_, i) => {\n    return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);\n  });\n};",
    "description": "Creates an array of elements, grouped based on their position in the original arrays.\n\n- Use `Math.max()`, `Function.prototype.apply()` to get the longest array in the arguments.\n- Create an array with that length as return value and use `Array.from()` with a mapping function to create an array of grouped elements.\n- If lengths of the argument arrays vary, `undefined` is used where no value could be found.",
    "example": "zip(['a', 'b'], [1, 2], [true, false]); // [['a', 1, true], ['b', 2, false]]\nzip(['a'], [1, 2], [true, false]); // [['a', 1, true], [undefined, 2, false]]",
    "id": "zip",
    "tags": [
      "array",
      "intermediate"
    ]
  },
  {
    "code": "const zipObject = (props, values) =>\n  props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});",
    "description": "Associates properties to values, given array of valid property identifiers and an array of values.\n\n- Use `Array.prototype.reduce()` to build an object from the two arrays.\n- If the length of `props` is longer than `values`, remaining keys will be `undefined`.\n- If the length of `values` is longer than `props`, remaining values will be ignored.",
    "example": "zipObject(['a', 'b', 'c'], [1, 2]); // {a: 1, b: 2, c: undefined}\nzipObject(['a', 'b'], [1, 2, 3]); // {a: 1, b: 2}",
    "id": "zipObject",
    "tags": [
      "array",
      "object",
      "intermediate"
    ]
  },
  {
    "code": "const zipWith = (...array) => {\n  const fn =\n    typeof array[array.length - 1] === 'function' ? array.pop() : undefined;\n  return Array.from({ length: Math.max(...array.map(a => a.length)) }, (_, i) =>\n    fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])\n  );\n};",
    "description": "Creates an array of elements, grouped based on the position in the original arrays and using a function to specify how grouped values should be combined.\n\n- Check if the last argument provided is a function.\n- Use `Math.max()` to get the longest array in the arguments.\n- Use `Array.from()` to create an array with appropriate length and a mapping function to create array of grouped elements.\n- If lengths of the argument arrays vary, `undefined` is used where no value could be found.\n- The function is invoked with the elements of each group.",
    "example": "zipWith([1, 2], [10, 20], [100, 200], (a, b, c) => a + b + c); // [111, 222]\nzipWith(\n  [1, 2, 3],\n  [10, 20],\n  [100, 200],\n  (a, b, c) =>\n    (a != null ? a : 'a') + (b != null ? b : 'b') + (c != null ? c : 'c')\n); // [111, 222, '3bc']",
    "id": "zipWith",
    "tags": [
      "array",
      "advanced"
    ]
  }
]