npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sorters

v1.1.0

Published

Sort function generators

Downloads

71

Readme

Sorters is a compact package for generating Javascript array sort comparators that handle things like null values, descending sort, and multi-level comparisons.

Usage

The sorter function builds and returns a comparator function that uses the specified comparison order. This returned function can be used with Array.sort or just to order any two objects.

import { sorter } from 'sorters';

let data = [
  { a: 5, b: 'strb', c: new Date('2017-06-01') },
  { a: 2, b: 'stra', c: new Date('2018-05-01') },
  { a: null, b: null },
  { a: 2, b: 'strc', c: new Date('2018-02-01') },
];

// Sort first on `c`, counting nullish values as higher than the others.
// If `c` is equal on two objects, use `a` in ascending order, and if `a` is equal then sort by
// `b` in descending order.
data.sort(sorter(
    { value: 'c', nulls: Nulls.High },
    'a',
    { value: (val) => val.b, descending: true, type: ValueType.String }
  ));
  

// Result: 
[
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z },
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: null, b: null }
]

Examples

Sort by the value of the a field in ascending order.


> data.sort(sorter('a'))
[
  { a: null, b: null },
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }
]

Sort by the value of the a field in descending order.

> data.sort(sorter({ value: 'a', descending: true }));
[
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z },
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: null, b: null }
]

Sort by the month value of the c field.

// Note the `?.` operator to handle when `c` is missing.
> data.sort(sorter((obj) => obj.c?.getUTCMonth()));
[
  { a: null, b: null },
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }
]

Sort by the a field, and when comparing objects with the same value for a, compare b instead.

> data.sort(sorter('a', 'b'));
[
  { a: null, b: null },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }
]

Same, but when comparing b use descending order.

> data.sort(sorter('a', { value: 'b', descending: true }));
[
  { a: null, b: null },
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }
]

Sort by a ascending, and counting nullish values as higher than the others.

> data.sort(sorter({ value: 'a', nulls: Nulls.High /* or just 'high` if not using Typescript */))
[
  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },
  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },
  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z },
  { a: null, b: null }
]

Arguments

Each argument to the sorter function is an object that represents how to perform a single level of the sort.

If two items in the array are equal for a particular level, then the next level is tried, and so on until a difference is found or all levels have equal values.

The object contains four properties:

value

value specifies which field to access in each item. It can be a function, a string specifying a path, or an array specifying a path.

When value is the only argument required, it can also be passed directly as the argument instead of wrapping it with an object, as in the 'a' argument in the example above.

descending

descending is an optional boolean indicating that the sort should be done in descending order. If omitted, the sort is done in ascending order.

type

type gives the sorter a hint as the to type of data it will encounter. Typescript users can use the ValueType enum, and others can use the values string, number, and date.

If some of the data does not match the specified type, you will likely encounter incorrect results or an error.

The default value is any, which will detect the type of value as it is sorted and act appropriately.

export enum ValueType {
  Any = 'any',
  String = 'string',
  Number = 'number',
  Date = 'date',
}

nulls

How to treat null or undefined values in the data. Typescript users can use the Nulls enum, while others can use the values low, high, and none.

export enum Nulls {
  /** Treat nulls as lower than any other values. This is the default setting. */
  Low = 'low',
  /** Treat nulls as higher than any other values. */
  High = 'high',
  /** Assume there are no nullish values in the data. This may cause exceptions if you are wrong. */
  None = 'none',
}

Using Nulls.None in data that contains nullish values will probably cause an error.