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

@pabra/sortby

v1.0.2

Published

Provide typesafe function to be passed to Array.prototype.sort() to sort an Array of Objects by multiple keys.

Downloads

46,884

Readme

@pabra/sortby

npm version npm bundle size (scoped) Codecov unit-tests npm-publish

play with sortby

What

If you want to sort an array of objects by multiple keys, you pass the object's key names in the order you want to sort them to sortby and get back a function that you can pass to Array.prototype.sort.

Goals are:

  • work with Array.prototype.sort
  • be typesafe
  • be lightweight/small
  • be usable in browser and node.js
  • do not have dependencies

Why

There are already many tools like this but I was unable to find any that is typesafe and Array.prototype.sort compatible.

Install

npm install --save @pabra/sortby
# or
yarn add @pabra/sortby

Getting Started

Let's assume we have a list of users.

const users = [
  { name: 'Bob', age: 23 },
  { name: 'Alice', age: 23 },
  { name: 'Chloe', age: 42 },
  { name: 'Bob', age: 21 },
];

Now we want to sort this array first by name and then by age.

users.sort((left, right) =>
  left.name < right.name ? -1
    : left.name > right.name ? 1
    : left.age < right.age ? -1
    : left.age > right.age ? 1
    : 0,
);

Just for 2 keys this is already alot of typing and easy to produce/overlook typos - especially if you have mixed ascending and descending order direction. How about this for the same result?

import { by } from '@pabra/sortby';

users.sort(by('name', 'age'));

Usage

In the following examples we assume following User object.

type User = {
  name: string;
  age: number;
};

Importing

Import sortby

import { by } from '@pabra/sortby';

Sort by key names ascending

For each key of your object that you want to sort by, you need to pass an argument to by function. If you want to sort your array of Users (User[]) ascending by the key "name" and then by "age", you have to pass those key names as 2 arguments to by.

by('name', 'age')

That will return a function that you can pass to Array.prototype.sort with a signature like this:

(left: User, right: User) => number

Sort descending

To sort descending for a key, you need to pass a tuple of key name and sort direction. Sort directions are abbreviated with asc for "ascending" and desc for "descending". To sort first descending by "name" and then descending by "age", you write:

by(['name', 'desc'], ['age', 'desc'])

Writing

by('name', 'age')

is just a shorthand for

by(['name', 'asc'], ['age', 'asc'])

Prepare a sortby function

If you need to sort User lists at multiple places the same way, you can prepare a sortby function to be reusable.

const userSort = by('name', 'age');

Then you can just use it where needed.

const finalUsers = users
  .filter(user => user.age > 23)
  .sort(userSort);

sortby works with generic types. userSort from above will have the following (simplified) type signature:

const userSort: (
  left: { name: any } & { age: any },
  right: { name: any } & { age: any },
) => number

This means, userSort will work on any object with keys "name" and "age". When you change the shape of your User type (eg. "name" => "firstName"), typescript will mark places where you pass userSort to sort functions instead of the place where you defined userSort.

To show typescript that this filter function is supposed to work on User objects, you can define it like this:

const userSort = by<User>('name', 'age');

The resulting (simplified) type signature looks like:

const userSort: (
  left: User,
  right: User,
) => number

Extractors

If you want to sort by nested objects or need to convert/manipulate a value before comparing, you can pass an extractor function instead of the key name. Let's assume you want to convert all user names to lower case before comping:

by(user => user.name.toLowerCase(), 'age')

For descending order, wrap it in a tuple as above:

by([user => user.name.toLowerCase(), 'desc'], 'age')

Tests

Run tests.

npm run test

See them succeed.

 PASS  __tests__/index.ts
  sort by name first
    ✓ sort by name asc (3 ms)
    ✓ sort by name asc, age asc (1 ms)
    ✓ sort by name asc, age desc
    ✓ sort by name desc, age asc (1 ms)
    ✓ sort by name desc, age desc
  sort explicitly asc
    ✓ sort by name explicitly asc (1 ms)
    ✓ sort by name asc, age asc
    ✓ sort by name asc, age desc (1 ms)
  sort by age first
    ✓ sort by age asc
    ✓ sort by age asc, name asc
    ✓ sort by age asc, name desc (1 ms)
    ✓ sort by age desc, name asc
    ✓ sort by age desc, name desc
  extractor
    ✓ sort by last reversed name asc, age asc (1 ms)
    ✓ sort by last reversed name desc, age asc

Test Suites: 1 passed, 1 total
Tests:       15 passed, 15 total
Snapshots:   0 total
Time:        2.371 s
Ran all test suites.