Skip to content

Latest commit

 

History

History
157 lines (123 loc) · 5.16 KB

README.md

File metadata and controls

157 lines (123 loc) · 5.16 KB

comparing

npm documentation minified + gzip Build codecov

Easily create descriptive comparators.

Features

Make sure to check out the documentation.

Installation

npm i comparing

Import all comparators, factories and types from 'comparing'.

Examples

All comparators are fully tested, so you can find more examples in the unit tests. A lot of comparators also have examples in their documentation.

Basic usage

import { naturalOrder } from 'comparing';

const actual = [4, 1, 3, 5].sort(naturalOrder);
expect(actual).toEqual([1, 3, 4, 5]);
const comparator: Comparator<string | null> = composeComparators([nullishFirst, localeCompare]);
const actual = ['A', 'a', 'b', null, 'B'].sort(comparator);
expect(actual).toEqual([null, 'a', 'A', 'b', 'B']);

const reversedComparator = reverseComparator(comparator);
const actualReversed = ['A', 'a', 'b', null, 'B'].sort(reversedComparator);
expect(actual).toEqual(['B', 'b', 'A', 'a', null]);

Comparing objects

The following example shows how to sort an array of objects, which have an optional order property that should take precedence when sorting. If equal or not present, then the objects should be sorted by their name property.

const nameComparator: Comparator<{ name: string }> = compareBy((x) => x.name, ignoreCase);
const orderComparator = compareBy((x) => x.order, composeComparators([nullishLast, naturalOrder]));
const myObjectComparator = composeComparators([orderComparator, nameComparator]);

const actual = [
  { name: 'B', order: 1 },
  { name: 'F' },
  { name: 'C', order: 3 },
  { name: 'A', order: 1 },
  { name: 'D' },
  { name: 'E', order: 2 },
].sort(myObjectComparator);

expect(actual).toEqual([
  { name: 'A', order: 1 },
  { name: 'B', order: 1 },
  { name: 'E', order: 2 },
  { name: 'C', order: 3 },
  { name: 'D' },
  { name: 'F' },
]);

Usage with other libraries

The library has no dependencies, thus only creates and works with the JavaScript objects and functions you already know.

Compare with dot path

import { compareBy } from 'comparing';
import get from 'lodash/fp/get';

const abcComparator = compareBy(get('a.b.c'));

const data = [
  { a: { b: { c: 1 } } },
  { a: { b: { c: 0 } } },
  { a: { b: { c: 2 } } },
].sort(abcComparator);

expect(data).toEqual([
  { a: { b: { c: 0 } } },
  { a: { b: { c: 1 } } },
  { a: { b: { c: 2 } } },
]);

Sort dependencies

import {
  compareBy,
  comparatorForOrder,
  composeComparators,
  Comparator,
} from 'comparing';
import toposort from 'toposort';

const graph = [
  // must first put on the shirt before the jacket, and so on ...
  ['put on your shirt', 'put on your jacket'],
  ['put on your shorts', 'put on your jacket'],
  ['put on your shorts', 'put on your shoes'],
];

const taskComparator = comparatorForOrder(toposort(graph));
const comparator: Comparator<{ day: number; task: string }> = composeComparators([
  compareBy((x) => x.day), // naturalOrder implicitly
  compareBy((x) => x.task, taskComparator),
]);

const todoList = [
  { day: 0, task: 'put on your jacket' },
  { day: 0, task: 'put on your shirt' },
  { day: 1, task: 'put on your shoes' },
  { day: 2, task: 'put on your shirt' },
  { day: 1, task: 'put on your jacket' },
  { day: 1, task: 'put on your shorts' },
].sort(comparator);

expect(todoList).toEqual([
  { day: 0, task: 'put on your shirt' },
  { day: 0, task: 'put on your jacket' },
  { day: 1, task: 'put on your shorts' },
  { day: 1, task: 'put on your jacket' },
  { day: 1, task: 'put on your shoes' },
  { day: 2, task: 'put on your shirt' },
]);