Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

list-fns

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

list-fns

A collection of utility functions to be used with .map, .filter, .sort and .reduce

  • 0.3.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
96
decreased by-46.37%
Maintainers
1
Weekly downloads
 
Created
Source

list-fns

npm version

This library contains higher order functions for doing common list operations to enable a more declarative style when working with lists. File size is prioritized over performance (several of the functions are O(n^2)); this is not recommended for use with very large datasets.

Example

import { byProperty, get, uniqueByProperty } from "list-fns";

const people = [
  { name: "Jack", age: 44 },
  { name: "Jack", age: 60 },
  { name: "Jane", age: 20 },
];

people
  .filter(
    (person, index) => index === people.findIndex(p => p.name === person.name)
  )
  .sort((a, b) => (a.age < b.age ? -1 : a.age > b.age ? 1 : 0))
  .map(person => person.name); // ["Jane", "Jack"]

people
  .filter(uniqueByProperty("name"))
  .sort(byProperty("age"))
  .map(get("name")); // ["Jane", "Jack"]

Install

npm install list-fns

Disclaimer about sorting

This library contains functions to be used with [].sort(). Always be mindful of the fact that .sort() and .reverse() will mutate the original list. If .sort() is the first method you're calling on a list you should probably clone it first in order to avoid unexpected behavior:

[...list].sort();
list.slice().sort();
[].concat(list).sort();

Functions

Table of contents

by

by: <T>(func: (el: T) => any) => (a: T, b: T) => 0 | 1 | -1

Use with: sort

Sort the elements by the return values of the provided function. Supports sorting by boolean values (elements that are true first).

[{ a: 2 }, { a: 1 }].sort(by(el => el.a)); // Returns [{ a: 1 }, { a: 2 }]

Implementation

const by = <T>(func: (el: T) => any) => (a: T, b: T) => {
  const A = func(a),
    B = func(b);
  if (typeof A === "boolean") return A && !B ? -1 : !A && B ? 1 : 0;
  return A < B ? -1 : A > B ? 1 : 0;
}

byProperty

byProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey) => (a: TObject, b: TObject) => 0 | 1 | -1

Use with: sort

Sort the elements by the property value at the provided key (can also be an array index). Supports sorting by boolean values (elements that are true first).

[{ a: 2 }, { a: 1 }].sort(byProperty('a')); // Returns [{ a: 1 }, { a: 2 }]
[["a", 2], ["a", 1]].sort(byProperty(1)); // Returns [["a", 1], ["a", 2]]

Implementation

const byProperty = <TObject extends object, TKey extends keyof TObject>(
  key: TKey
) => by<TObject>(get(key))

countBy

countBy: <T>(func: (el: T) => boolean) => (acc: number, el: T) => number

Use with: reduce

Counts the number of times func returned true for the list elements. A number must be passed to the second argument of reduce .

["a", "a", "b"].reduce(countBy(el => el === "a"), 0); // Returns 2

Implementation

const countBy = <T>(func: (el: T) => boolean) => (acc: number, el: T) =>
  acc + (func(el) ? 1 : 0)

duplicates

duplicates: (el: unknown, _: number, list: unknown[]) => boolean

Use with: filter

Returns duplicates

[1, 1, 1, 2].filter(duplicates); // Returns [1, 1, 1]

Implementation

const duplicates = duplicatesBy(el => el)

duplicatesBy

duplicatesBy: <T>(func: (el: T) => unknown) => (el: T, _: number, list: T[]) => boolean

Use with: filter

Returns all duplicates (compared by the provided function)

[{ a: 1 }, { a : 1 }, { a: 2 }].filter(duplicatesBy(el => el.a)); // Returns [{ a: 1 }, { a: 1 }]

Implementation

const duplicatesBy = <T>(func: (el: T) => unknown) => (
  el: T,
  _: number,
  list: T[]
) => numberOfOccurencesBy(list, el, func) > 1

duplicatesByProperty

duplicatesByProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey) => (el: TObject, _: number, list: TObject[]) => boolean

Use with: filter

Returns duplicates by comparing the key property of the elements

[{ a: 1 }, { a: 1 }].filter(duplicatesByProperty('a')); // Return [{ a: 1 }, { a: 1 }]

Implementation

const duplicatesByProperty = <
  TObject extends object,
  TKey extends keyof TObject
>(
  key: TKey
) => duplicatesBy<TObject>(get(key))

exclude

exclude: <T>(list: T[]) => (el: T) => boolean

Use with: filter

Removes the provided elements from the list

[1, 2, 3, 4].filter(exclude([1, 2])); // Returns [3, 4]

Implementation

const exclude = <T>(list: T[]) => (el: T) =>
  findIndex(list, a => a === el) === -1

excludeBy

excludeBy: <T>(func: (el: T) => unknown, list: T[]) => (el: T) => boolean

Use with: filter

Removes the provided elements from the list compared by running func on each element

[{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]
  .filter(excludeBy(el => el.a, [{ a: 1 }, { a: 2 }]));
  // Returns [{ a: 3 }, { a: 4 }]

Implementation

const excludeBy = <T>(func: (el: T) => unknown, list: T[]) => (el: T) =>
  findIndex(list, a => func(a) === func(el)) === -1

excludeByProperty

excludeByProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey, list: TObject[]) => (el: TObject) => boolean

Use with: filter

Removes the provided elements from the list compared at key

[{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]
  .filter(excludeByProperty('a', [{ a: 1 }, { a: 2 }]));
  // Returns [{ a: 3 }, { a: 4 }]

Implementation

const excludeByProperty = <
  TObject extends object,
  TKey extends keyof TObject
>(
  key: TKey,
  list: TObject[]
) => excludeBy(get(key), list)

get

get: {
  <TObject extends object, TKey1 extends keyof TObject, TKey2 extends keyof TObject[TKey1], TKey3 extends keyof TObject[TKey1][TKey2]>(key1: TKey1, key2: TKey2, key3: TKey3): (obj: TObject) => TObject[TKey1][TKey2][TKey3];
  <TObject extends object, TKey1 extends keyof TObject, TKey2 extends keyof TObject[TKey1]>(key1...;
}

Use with map or filter

Returns the value at key (can also be an array index). Supports up to three keys of depth.

[{ a: 1 }, { a: 2 }].map(get('a')); // Returns [1, 2]
[["a", 1], ["a", 2]].map(get(1)); // Returns [1, 2]
[{ a: { b: { c: 1 } } }].map(get('a', 'b', 'c')); // Returns [1]

Implementation

export function get<
  TObject extends object,
  TKey1 extends keyof TObject,
  TKey2 extends keyof TObject[TKey1],
  TKey3 extends keyof TObject[TKey1][TKey2]
>(key1: TKey1, key2?: TKey2, key3?: TKey3) {
  return (obj: TObject) => {
    if (key3 && key2)
      return obj && obj[key1] && obj[key1][key2] && obj[key1][key2][key3];
    if (key2) return obj && obj[key1] && obj[key1][key2];
    return obj && obj[key1];
  };
}

groupBy

groupBy: <K extends string, V>(func: (el: V) => K) => (acc: Record<K, V[]>, el: V) => Record<K, V[]>

Use with: reduce

Given a key-returning function, returns an object of lists of elements. A second argument must be passed to reduce . For javascript an empty object is enough. For typescript an object with properties or a type cast is required.

[{ age: 10 }, { age: 80 }].reduce(
  groupBy(el => (el.age > 30 ? "old" : "young")),
  { old: [], young: [] }
); // Returns { old: [{ age: 80 }], young: [{ age: 10 }]}

Implementation

const groupBy = <K extends string, V>(func: (el: V) => K) => (
  acc: Record<K, V[]>,
  el: V
): Record<K, V[]> => {
  const groupName = func(el),
    group: V[] = acc[groupName] || [];
  return Object.assign({}, acc, { [groupName]: group.concat(el) });
}

intersection

intersection: <T>(list: T[]) => (el: T) => boolean

Use with: filter

Returns a list of elements that are present in both lists

[1, 2, 3].filter(intersection([2, 3, 4])); // Returns [2, 3]

Implementation

const intersection = <T>(list: T[]) => (el: T) =>
  findIndex(list, a => a === el) !== -1

intersectionBy

intersectionBy: <T>(func: (el: T) => unknown, list: T[]) => (el: T) => boolean

Use with: filter

Returns a list of elements that are present in both lists compared by running func on each element

[{ a: 1 }, { a: 2 }, { a: 3 }]
  .filter(intersectionBy(el => el.a, [{ a: 2 }, { a: 3 }, { a: 4 }]));
  // Returns [{ a: 2 }, { a: 3 }]

Implementation

const intersectionBy = <T>(func: (el: T) => unknown, list: T[]) => (
  el: T
) => findIndex(list, a => func(a) === func(el)) !== -1

intersectionByProperty

intersectionByProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey, list: TObject[]) => (el: TObject) => boolean

Use with: filter

Returns a list of elements that are present in both lists compared at key

[{ a: 1 }, { a: 2 }, { a: 3 }]
  .filter(intersectionByProperty("a", [{ a: 2 }, { a: 3 }, { a: 4 }]));
  // Returns [{ a: 2 }, { a: 3 }]

Implementation

const intersectionByProperty = <
  TObject extends object,
  TKey extends keyof TObject
>(
  key: TKey,
  list: TObject[]
) => intersectionBy(get(key), list)

isDefined

isDefined: <T>(x: T | undefined) => x is T

Use with: filter

Removes elements that are undefined

[1, undefined, 2].filter(isDefined); // Returns [1, 2]

Implementation

const isDefined = <T>(x: T | undefined): x is T =>
  typeof x !== "undefined"

max

max: (acc: number, el: number) => number

Use with: reduce

Returns the largest value in the list

[1,2,3,4].reduce(max); // Returns 4

Implementation

const max = (acc: number, el: number) => Math.max(acc, el)

maxBy

maxBy: <T>(func: (el: T) => number) => (acc: T, el: T) => T

Use with: reduce

Returns the element that returned the largest value from func

[{ a: 1 }, { a: 2 }, { a: 3 }].reduce(maxBy(el => el.a)); // Returns { a: 3 }

Implementation

const maxBy = <T>(func: (el: T) => number) => (acc: T, el: T) =>
  func(el) > func(acc) ? el : acc

maxByProperty

maxByProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey) => (acc: TObject, el: TObject) => TObject

Use with: reduce

Returns the element that has the largest value at key

[{ a: 1 }, { a: 2 }, { a: 3 }].reduce(maxByProperty("a")); // Returns { a: 3 }

Implementation

const maxByProperty = <
  TObject extends object,
  TKey extends keyof TObject
>(
  key: TKey
) => (acc: TObject, el: TObject) => (el[key] > acc[key] ? el : acc)

min

min: (acc: number, el: number) => number

Use with: reduce

Returns the smallest value in the list

[1,2,3,4].reduce(min); // Returns 1

Implementation

const min = (acc: number, el: number) => Math.min(acc, el)

minBy

minBy: <T>(func: (el: T) => number) => (acc: T, el: T) => T

Use with: reduce

Returns the element that returned the smallest value from func

[{ a: 1 }, { a: 2 }, { a: 3 }].reduce(minBy(el => el.a)); // Returns { a: 1 }

Implementation

const minBy = <T>(func: (el: T) => number) => (acc: T, el: T) =>
  func(el) < func(acc) ? el : acc

minByProperty

minByProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey) => (acc: TObject, el: TObject) => TObject

Use with: reduce

Returns the element that has the smallest value at key

[{ a: 1 }, { a: 2 }, { a: 3 }].reduce(minByProperty("a")); // Returns { a: 1 }

Implementation

const minByProperty = <
  TObject extends object,
  TKey extends keyof TObject
>(
  key: TKey
) => (acc: TObject, el: TObject) => (el[key] < acc[key] ? el : acc)

partition

partition: <T>(func: (el: T) => boolean) => (acc: T[][], el: T) => T[][]

Use with: reduce

Splits the input list into two lists. The first list contains elements for which the given function returned true , the second contains elements for which the function returned false .

[{ age: 10 }, { age: 80 }].reduce(partition(el => el.age > 30), []);
// Returns [[{ age: 80 }], [{ age: 10 }]]

Implementation

const partition = <T>(func: (el: T) => boolean) => (
  acc: T[][],
  el: T
) => {
  const a0 = acc[0] || [],
    a1 = acc[1] || [];
  return func(el) ? [a0.concat(el), a1] : [a0, a1.concat(el)];
}

sum

sum: (acc: number, element: number) => number

Use with: reduce

Sum a list of numbers

[1, 2, 3].reduce(sum); // Returns 6

Implementation

const sum = (acc: number, element: number) => acc + element

sumBy

sumBy: {
  <T>(func: (el: T) => number): (acc: number, el: T) => number;
  <T>(func: (el: number) => number): (acc: number, el: number) => number;
}

Use with: reduce

Sums the values returned from the provided function. If the list elements aren't numbers, a number must be passed as the second argument to reduce .

[{ a: 1 }, { a: 2 }].reduce(sumBy(el => el.a), 0); // Returns 3
[1.5, 2.5].reduce(sumBy(Math.floor)); // Returns 3

Implementation

export function sumBy<T>(func: (el: T | number) => number) {
  return (acc: number, el: T | number) =>
    typeof el === "number" ? func(acc) + func(el) : acc + func(el);
}

sumByProperty

sumByProperty: <TObject extends { [key: string]: number; }, TKey extends keyof TObject>(key: TKey) => (acc: number, el: TObject) => number

Use with: reduce

Sums the values at key for all elements. A number must be passed to the second argument of reduce .

[{ a: 1 }, { a: 2 }].reduce(sumByProperty('a'), 0); // Returns 3

Implementation

const sumByProperty = <
  TObject extends { [key: string]: number },
  TKey extends keyof TObject
>(
  key: TKey
) => (acc: number, el: TObject) => acc + el[key]

unique

unique: (el: unknown, index: number, list: unknown[]) => boolean

Use with: filter

Removes duplicates from list

[1,1,1,2].filter(unique); // Returns [1, 2]

Implementation

const unique = uniqueBy(el => el)

uniqueBy

uniqueBy: <T>(func: (el: T) => unknown) => (el: T, index: number, list: T[]) => boolean

Use with: filter

Removes duplicates by comparing elements according to the provided function

[{ a: 1 }, { a : 1 }].filter(uniqueBy(el => el.a)); // Returns [{ a: 1 }]

Implementation

const uniqueBy = <T>(func: (el: T) => unknown) => (
  el: T,
  index: number,
  list: T[]
) => index === findIndex(list, t => func(t) === func(el))

uniqueByProperty

uniqueByProperty: <TObject extends object, TKey extends keyof TObject>(key: TKey) => (el: TObject, index: number, list: TObject[]) => boolean

Use with: filter

Removes duplicates by comparing the key property of the elements

[{ a: 1 }, { a: 1 }].filter(uniqueByProperty('a')); // Return [{ a: 1 }]

Implementation

const uniqueByProperty = <
  TObject extends object,
  TKey extends keyof TObject
>(
  key: TKey
) => uniqueBy<TObject>(get(key))

FAQs

Package last updated on 04 Sep 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc