compare-builder
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

Compare Builder

A series of Tools to make sorting Arrays easier to work with, particularly when sorting objects.

Can be used to build compare functions to pass to Array.sort(), or can extend Array directly to include new methods Array.sortByAsc(), Array.sortByDesc() and Array.buildSort().asc().desc().sort()

Example - Sorting Primitives

// sorting Primitives
const primitiveInput = ["1", "3", "2"]
// using Array Extensions
primitiveInput.sortByAsc() // ["1", "2", "3"]
primitiveInput.sortByDesc() // ["3", "2", "1"]
// using Comparators
primitiveInput.sort(byAttributeAsc(i => i)) // ["1", "2", "3"]
primitiveInput.sort(byAttributeDesc(i => i)) // ["3", "2", "1"]

Example - Sorting Objects

// Sorting Objects
const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
// using Array Extensions
objectInput.sortByAsc(obj => obj.id) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]
objectInput.sortByDesc(obj => obj.id) // [{id: "3", foo: "a"}, {id: "2", foo: "b"}, {id: "1", foo: "c"}]
objectInput.buildSort()
  .asc(obj => obj.id)
  .desc(obj => obj.foo)
  .sort() // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

// using Comparators
objectInput.sort(byAttributeAsc(obj => obj.id)) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]
objectInput.sort(byAttributeDesc(obj => obj.id)) // [{id: "3", foo: "a"}, {id: "2", foo: "b"}, {id: "1", foo: "c"}]
objectInput.sort(
  new CompareBuilder()
    .asc(obj => obj.id)
    .desc(obj => obj.foo)
    .build() // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]
)

Installation

npm install --save compare-builder

Documentation

Extending Array with sortByAsc() / sortByDesc() / buildSort()

To add the sortByAsc() / sortByDesc() / buildSort() methods to JS's base Array interface, you can import the extension by including:

import "compare-builder/extend-array-with-sort-by"

into your codebase at some point before attempting to call [].sortByAsc()

// somewhere in your initialization logic
import "compare-builder/extend-array-with-sort-by"

// ...

// Array now has a sortByAsc() method
const result = ["1", "3", "2"].sortByAsc() // ["1", "2", "3"]

Sorting by extracted Attributes

Every method in this module relies on using an Attribute Extractor to choose the attribute to sort the items in the Array by.

Items are sorted using the native Javascript behaviour for the > and < operators.

So if an attribute is extracted that does not interact in a consistent way with the > and < operators, the resulting sort will be inconsistent.

The recommendation is to use the Attribute Extractor to sort by a Primitive type, probably a string or number.


Function: Array.sortByAsc()

Definition: <T, R> (attributeExtractor?:AttributeExtractor<T, R>) => Array<T>

Extension on the Array interface.

sortByAsc() takes an optional Attribute Extractor function and sorts the Array in ascending order using the output of the Attribute Extractor for sorting.

Items are sorted in place, consistent with the current Array.sort() behaviour.

const primitiveInput = ["1", "3", "2"]
primitiveInput.sortByAsc() // ["1", "2", "3"]

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sortByAsc(obj => obj.id) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

Function: Array.sortByDesc()

Definition: <T, R> (attributeExtractor?:AttributeExtractor<T, R>) => Array<T>

Extension on the Array interface.

sortByDesc() takes an optional Attribute Extractor function and sorts the Array in descending order using the output of the Attribute Extractor for sorting.

Items are sorted in place, consistent with the current Array.sort() behaviour.

const primitiveInput = ["1", "3", "2"]
primitiveInput.sortByDesc() // ["3", "2", "1"]

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sortByDesc(obj => obj.id) // [{id: "3", foo: "a"}, {id: "2", foo: "b"}, {id: "1", foo: "c"}]

Function: Array.buildSort()

Definition: <T> buildSort: () => ArraySorter<T>

Extension to the Array interface.

buildSort() returns an ArraySorter which allows the sorting of an Array to be more finely controlled, sorting in multiple directions by different attributes.

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.buildSort()
  .asc(obj => obj.id)
  .desc(obj => obj.foo)
  .sort() // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

See the documentation on ArraySorter for more information on how it works.


Class: new ArraySorter()

Definition:

interface ArraySorter<T> {
  constructor(arrayToSort:Array<T>): ArraySorter<T>
  asc<R>(attributeExtractor:AttributeExtractor<T, R>): ArraySorter<T>,
  desc<R>(attributeExtractor:AttributeExtractor<T, R>): ArraySorter<T>,
  sort(): Array<T>,
  toSorted(): Array<T>
}

A class for sorting an Array based on different Comparators.

It takes an input Array in it's constructor, then a series of Comparators are configured using the asc() / desc() methods, then the input Array is sorted using these Comparators using the sort() / toSorted() methods.

This class works in a similar way to CompareBuilder but instead of returning the Comparator, it sorts the Array directly.

constructor() - Takes an input Array that will be sorted

asc() - Adds a sort by Ascending Comparator

desc() - Adds a sort by Descending Comparator

sort() - Combines the Comparators, sorts the Array in place, according to the Comparators, and returns the Array

toSorted() - Combines the Comparators, makes a shallow copy and sorts the Array, according to the Comparators, and returns the Array

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
new ArraySorter(objectInput)
  .asc(obj => obj.id)
  .desc(obj => obj.foo)
  .sort() // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

Function: byAttributeAsc()

Definition: <T, R>(attributeExtractor:AttributeExtractor<T, R>) => Comparator<T>

Function that takes an Attribute Extractor and returns a Comparator that can be used in Array.sort().

The Comparator will sort the Array by the extracted attribute in ascending order.

const primitiveInput = ["1", "3", "2"]
primitiveInput.sort(byAttributeAsc(i => i)) // ["1", "2", "3"]

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sort(byAttributeAsc(obj => obj.id)) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

Function: byAttributeDesc()

Definition: <T, R>(attributeExtractor:AttributeExtractor<T, R>) => Comparator<T>

Function that takes an Attribute Extractor and returns a Comparator that can be used in Array.sort().

The Comparator will sort the Array by the extracted attribute in descending order.

const primitiveInput = ["1", "3", "2"]
primitiveInput.sort(byAttributeDesc(i => i)) // ["3", "2", "1"]

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sort(byAttributeDesc(obj => obj.id)) // [{id: "3", foo: "a"}, {id: "2", foo: "b"}, {id: "1", foo: "c"}]

Function: combine()

Definition: <T>(...comparators:Array<Comparator<T>>) => Comparator<T>

Function that takes several Comparators and combines them to produce a new Comparator that sorts in the order of the input Comparators.

This allows Comparators to be combined to sort by one attribute, then a second, then a third.

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sort(
  combine(
    byAttributeAsc(obj => obj.id),
    byAttributeDesc(obj => obj.foo)
  )
) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

Class: new CompareBuilder()

Definition:

interface CompareBuilder<T> {
  constructor(): CompareBuilder<T>
  asc<R>(attributeExtractor: AttributeExtractor<T, R>): CompareBuilder<T>,
  desc<R>(attributeExtractor: AttributeExtractor<T, R>): CompareBuilder<T>,
  build(): Comparator<T>
}

A builder class for constructing a Comparator from multiple different Attribute Extractors.

It is a potentially more convenient option than using combine() with byAttributeAsc() / byAttributeDesc() directly.

asc() - Adds a sort by Ascending comparator

desc() - Adds a sort by Descending comparator

build() - Combines the Comparators and returns the combined Comparator

const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sort(
  new CompareBuilder()
    .asc(obj => obj.id)
    .desc(obj => obj.foo)
    .build()
) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

Function: sortByAsc()

Definition: <T, R>(attributeExtractor:AttributeExtractor<T, R>) => CompareBuilder<T>

A convenience method to make calling CompareBuilder easier to use.

It is equivalent to calling:

new CompareBuilder().asc(attributeExtractor)
const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sort(
  sortByAsc(obj => obj.id)
    .desc(obj => obj.foo)
    .build()
) // [{id: "1", foo: "c"}, {id: "2", foo: "b"}, {id: "3", foo: "a"}]

Function: sortByDesc()

Definition: <T, R>(attributeExtractor:AttributeExtractor<T, R>) => CompareBuilder<T>

A convenience method to make calling CompareBuilder easier to use.

It is equivalent to calling:

new CompareBuilder().desc(attributeExtractor)
const objectInput = [{id: "1", foo: "c"}, {id: "3", foo: "a"}, {id: "2", foo: "b"}]
objectInput.sort(
  sortByDesc(obj => obj.id)
    .asc(obj => obj.foo)
    .build()
) // [{id: "3", foo: "a"}, {id: "2", foo: "b"}, {id: "1", foo: "c"}]

Package Sidebar

Install

npm i compare-builder

Weekly Downloads

2

Version

1.0.0

License

MIT

Unpacked Size

26.3 kB

Total Files

13

Last publish

Collaborators

  • doogal