Useful comparator functions written on Typescript
npm install type-comparator
Useful comparator functions written on Typescript (But you can use it on your JS project)

- Type Comparator
- Table of Contents
- Installation
- Usage
- Base comparators: asc and desc
- Functional way
- Function reverse(comparator)
- Function map(mapper, comparator)
- Function condition(conditionFn, comparatorA, comparatorB)
- Function queue(comparators)
- Chaining way
- Basic usage
- Chain .reverse()
- Chain .map(mapper)
- Chain .if(conditionFn)
- Chain .then(comparator)
- Chain .elif(conditionFn)
- Chain .else(comparator)
- Chain .use(comparators)
- Something more complex?... Ok!
- Q&A
- Support
- Contributing
``sh`
npm i type-comparator
asc is simple comparator contains just base comparison logic.
It works well with numbers...
`ts
const array = [17, 4, -17, 42, -3, 0];
// [-17, -3, 0, 4, 17, 42]
array.slice().sort(asc);
// [42, 17, 4, 0, -3, -17]
array.slice().sort(desc);
`
And with strings...
`ts
const array = ['aaa', 'bax', 'a', 'x', 'ax', 'ab', 'ba', 'bx'];
// ["a", "aaa", "ab", "ax", "ba", "bax", "bx", "x"]
array.slice().sort(asc);
// ["x", "bx", "bax", "ba", "ax", "ab", "aaa", "a"]
array.slice().sort(desc);
`
Even with dates...
`ts
const array = [new Date(2018, 0, 1), new Date(2017, 0, 1), new Date(2019, 0, 1)];
// [Date(2017, 0, 1), Date(2018, 0, 1), Date(2019, 0, 1)]
array.slice().sort(asc);
// [Date(2019, 0, 1), Date(2018, 0, 1), Date(2017, 0, 1)]
array.slice().sort(desc);
`
Actually it works well with everything comparable by > and <.
NOTE Every values which are neither > nor < are equal.
As you can see below, the initial order remains. If you want to sort by value of some item property, take a look on map function.
`ts
var array1 = [{a: 1}, {a: 5}];
var array2 = [{a: 5}, {a: 1}];
array1.slice().sort(asc); // [{a: 1}, {a: 5}]
array2.slice().sort(asc); // [{a: 5}, {a: 1}]
array1.slice().sort(desc); // [{a: 1}, {a: 5}]
array2.slice().sort(desc); // [{a: 5}, {a: 1}]
`
*
#### Function reverse(comparator)`
Just swap comparator args.ts
import { asc, cmp, reverse } from 'type-comparator';
const functionalCmp = reverse(asc);
const array = [17, 4, -17, 42, -3, 0];
// [ 42, 17, 4, 0, -3, -17 ]
array.slice().sort(functionalCmp);
`
#### Function map(mapper, comparator)mapper
Maps each args with and apply comparator.
`ts
import { asc, cmp, map } from 'type-comparator';
const mapper = x => x.a;
const comparator = map(mapper, asc);
const array = [{ a: 15 }, { a: 5 }];
// [ { a: 5 }, { a: 15 } ]
array.slice().sort(comparator);
`
#### Function condition(conditionFn, comparatorA, comparatorB)comparatorA
Has following logic:
- Applies , if both args satisfy conditionFn.comparatorB
- Applies , if both args do not satisfy conditionFn.conditionFn
- Returns positive value, if only first arg satisfies .conditionFn
- Returns negative value, if only second arg satisfies .
`ts
import { asc, cmp, condition } from 'type-comparator';
const conditionFn = x => x % 2 === 0;
const comparator = condition(conditionFn, asc, desc);
const array = [17, 4, -17, 42, -3, 0];
// [ 17, -3, -17, 0, 4, 42 ]
array.slice().sort(comparator);
`
#### Function queue(comparators)comparators
Applies first comparator from . 0
- If comparator returns non-zero value, returns it as result.
- If comparator returns , apply next comparator from comparators. comparators
- If there is no more comparator in list, returns 0.
`ts
import { asc, cmp, desc, map, queue } from 'type-comparator';
const comparator = queue([
map(x => x.name, asc),
map(x => x.age, desc),
]);
const array = [
{ name: 'Alex', age: 21 },
{ name: 'Jane', age: 19 },
{ name: 'Alex', age: 26 },
];
// [
// { name: 'Alex', age: 26 },
// { name: 'Alex', age: 21 },
// { name: 'Jane', age: 19 }
// ]
array.slice().sort(comparator);
`
#### Basic usage
cmp() - just starts chaining..use(comparator) - applies comparator and terminates chaining.
Note: use() chain can work with any comparator function (not only produced by type-comparator)
`ts
import { asc, cmp } from 'type-comparator';
// same as just asc function
const comparator1 = cmp().use(asc);
// works like asc but just for numbers
const comparator2 = cmp().use((a, b) => a - b);
// not a lot of sense, but it's possible
const comparator3 = cmp().use(comparator1);
`
#### Chain .reverse()
`ts
import { asc, cmp, reverse } from 'type-comparator';
const comparator = cmp().reverse().use(asc);
const array = [17, 4, -17, 42, -3, 0];
// [ 42, 17, 4, 0, -3, -17 ]
array.slice().sort(comparator);
`.map(mapper)
#### Chain
`ts
import { asc, cmp, map } from 'type-comparator';
const mapper = x => x.a;
const comparator = cmp().map(mapper).use(asc);
const array = [{ a: 15 }, { a: 5 }];
// [ { a: 5 }, { a: 15 } ]
array.slice().sort(comparator);
`
#### Chain .if(conditionFn)conditionFn
Checks for each arg. .then
- Applies next chain, if both args satisfy conditionFn..else
- Applies next /.elif chain, if both args do not satisfy conditionFn.conditionFn
- Returns positive value, if only first arg satisfies .conditionFn
- Returns negative value, if only second arg satisfies .
Note: After .if() chain, only .then chain is available.`ts
import { asc, cmp } from 'type-comparator';
const conditionFn = x => x % 4 === 0;
const conditionFn2 = x => x % 2 === 0;
const chainingCmp = cmp()
.if(conditionFn).then(asc)
.elif(conditionFn2).then(asc)
.else(asc);
const array = [17, 4, -17, 42, -3, 0];
// [ -17, -3, 17, 42, 0, 4 ]
array.slice().sort(chainingCmp);
`
#### Chain .then(comparator)comparator
Applies , if condition from previous .if()chain satisfies for both args.
Note: After .then() chain, only .elif() or .else() chains are available..then()
Note: chain is available only after .if() or .elif() chains.
#### Chain .elif(conditionFn).if()
Works same chain.
Note: After .elif() chain, only .then() chain is available..elif()
Note: chain is available only after .then() chain.
#### Chain .else(comparator)comparator
Applies , if both args do not satisfy comparators from previous .if()/.elif chains.
Note: .else() chain is available only after .then() chain..else()
Note: chain finishes chaining and returns result comparator function.
#### Chain .use(comparators) queue(comparators)
Works same as and terminates chaining.
`ts
import { asc, cmp, desc } from 'type-comparator';
const comparator = cmp().use([
cmp().map(x => x.name).use(asc),
cmp().map(x => x.age).use(desc),
]);
const array = [
{ name: 'Alex', age: 21 },
{ name: 'Jane', age: 19 },
{ name: 'Alex', age: 26 },
];
// [
// { name: 'Alex', age: 26 },
// { name: 'Alex', age: 21 },
// { name: 'Jane', age: 19 }
// ]
array.slice().sort(comparator);
`
*
ts
import { asc, cmp, desc } from 'type-comparator';const comparator = cmp()
.map(x => x.a)
.use([
cmp()
.map(x => x.b)
.use(desc),
cmp()
.if(x => (x.b + x.c) % 2 === 0)
.map(x => x.c)
.use(asc),
]);
const array = [
{ a: { b: 1, c: 7 } },
{ a: { b: 1, c: 6 } },
{ a: { b: 1, c: 5 } },
{ a: { b: 1, c: 4 } },
{ a: { b: 1, c: 3 } },
{ a: { b: 3, c: 2 } },
];
// [
// { a: { b: 3, c: 2 } },
// { a: { b: 1, c: 4 } },
// { a: { b: 1, c: 6 } },
// { a: { b: 1, c: 3 } },
// { a: { b: 1, c: 5 } },
// { a: { b: 1, c: 7 } },
// ]
array.slice().sort(comparator);
`**
$3
Q: Should
reverse(cmp) be equals to reversed array with cmp ?A: In general, it should not.
Array.prototype.reverse just reverse all elements order, regardless its values.
When comparator suppose both values are equal, it returns 0. And these elements save original order.`ts
const array = [1, 2, 4];
const comparator = cmp().map(x => x % 2 === 0).use(asc);// [2, 4, 1]
array.slice().sort(reverse(comparator));
// [4, 2, 1]
array.slice().sort(comparator).reverse();
``Please open an issue for support.
Please contribute using Github Flow. Create a branch, add commits, and open a pull request.