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

1.2.0 • Public • Published

Utility methods for creating comparators, ie. function (left,right)=>number. Slightly more versatile than other packages I found.

  • ~ 700 bytes minified + gzipped without browser polyfills etc.


Documentation for all methods with examples.

Coverage report.


The drill:

npm install --save kagura

Typings for typescript are available.

Use the dist.js or dist.min.js for browser usage. Exposes a global object window.Kagura.


Compare objects by their id property:

// import this lib
const { byKey } = require("kagura")
// create array and sort it with a custom comparator
const array = [ {id: 6}, {id: 3} ]
array.sort(byKey(item => item.id));

If you are comparing simply by some property, you can also use byProp:

const { byProp } = require("kagura")

Compare objects by their data.id property in descending order:

byProp("data.id", inverse) // preferred
// equivalently you couse use
byKey(item => - item.data.id)
byKey(item => item.data.id, inverse)

Compare objects by their lastName property first, then firstName, then age.


Find all items equal to "cake".

["cake", "chocolate"].filter(equalTo("cake"))
["cake", "Cake", "chocolate"].filter(equalTo("cake"), ignoreCase)
[{name: "cake"}, {name: "chocolate"}]
  .filter(equalTo("cake", byKey("name")))
[{name: "cake"}, {name: "Cake"}, {name: "chocolate"}]
  .filter(equalTo("cake", byKey("name", ignoreCase)))

Compare objects by using the comparison operator > and <.

[9,7,8].sort(natural) // => [7,8,9]
[9,7,8].sort(inverse) // => [9,8,7]

Handling undefined

Sort order of undefined

undefined always compares as less than any other value. This is different than how Array#sort handles undefined, but in line with the idea that an undefined string represents a blank string, which sorts before other strings alphabetically. This behaviour is also useful when working with comparisons on multiple properties.

To illustrate this, consider the following list of users, sorted first by their given name, then by their family name.

const user1 = {given: "dave", family: "oxford"};
const user2 = {given: "dave", family: "carbide"};
const user3 = {given: "laura", family: "oxford"};
const user4 = {given: "laura", family: "borea"};
const user5 = {given: "odo", family: "frodo"};
const users = [user1, user2, user3, user4, user5];
const comparator = combine(byProp("given"), byProp("family"));
// => [user2, user1, user4, user3, user5]

Now assume we want to get all users whose given name is laura. We could iterate over all entries and apply a filter:

users.filter(user => user.given === "laura");

This works, but this takes O(n) time to run. Assuming the list is already sorted, a binary search runs in O(log(n)) time. We construct a virtual user object with only a given name {given: "laura"} and determine the position where it would sort in the ordered list.

const search = {given: "laura"};
const start = users.findIndex(user => comparator(search, user) <= 0);
// start === 2  

Since undefined sorts before any other value, the start position now points to the first user in the sorted list with a given name of laura. Now we can find all lauras by iterating from the start position until we encounter a user with a different given name.

for (let user = users[start]; user.given === `laura`; user= users[++start]) {
  // do something with the user
// => logs user4 and user3

This approach also works well with binary search trees that always keep their elements sorted.

Sorting arrays

The built-in array sort method always sorts undefined last, irrespective of the given comparator. Use one of the wrapper methods to sort undefined properly:

const { sort } = require("kagura");
// Comparator "natural" sorts undefind before any other value.
// But the built-in function always puts undefined last.
// => [1,2,3,undefined]
sort([1,2,undefined,3], natural)
// => [undefined, 1, 2, 3]


Probably not going to work on Windows.

git clone https://github.com/blutorange/js-kagura
cd js-kagura
npm install
npm run build

Change log

I use the following keywords:

  • Added A new feature that is backwards-compatible.
  • Changed A change that is not backwards-compatible.
  • Fixed A bug or error that was fixed.


  • Added sort wrappers, see above.
  • Fixed some typings regarding undefined. Some methods can handle undefined by setting the type parameter to T|undefined on the calling side.


  • Updated all methods to handle undefined values. See above for details.
  • Extracted common interfaces and types (Comparator, Predicate etc.) to their own package. This affects you only if you are using typescript and are referring to these types explicitly; in this case please import them from the package andross instead from this package kagura, see below.
// If using typescript, change this
import { Comparable, Comparator, Equator, KeyExtractor, Predicate } from "kagura";
// to
import { Comparable, Comparator, Equator, KeyExtractor, Predicate } from "andross";

Teh name

Senran Kagura. Which part of the human body are they always concerned with and keep comparing?



Package Sidebar


npm i kagura

Weekly Downloads






Unpacked Size

1.22 MB

Total Files


Last publish


  • blutorange