Skip to content
VersionSize

compareBy

The compareBy utility is a factory function that creates a comparator based on a selector function. It is ideal for sorting arrays of objects by a specific property or a computed value.

Implementation

View Source Code
ts
import { compare } from './compare';

/**
 * Compares two objects based on multiple selectors.
 * The comparison is done in the order of the selectors provided.
 * Each selector can be 'asc' for ascending or 'desc' for descending order.
 *
 * @example
 * ```ts
 * const compareByNameAndAge = compareBy<{ name: string; age: number }>({
 *   name: 'asc',
 *   age: 'desc',
 * });
 *
 * const a = { name: 'Alice', age: 30 };
 * const b = { name: 'Bob', age: 25 };
 *
 * console.log(compareByNameAndAge(a, b)); // -1 (Alice < Bob)
 * ```
 *
 * @param selectors - An object where keys are properties to compare and values are 'asc' or 'desc'.
 *
 * @returns A comparison function that can be used with array sorting methods.
 */
export const compareBy = <T>(selectors: Partial<Record<keyof T, 'asc' | 'desc'>>) => {
  const entries = Object.entries(selectors) as [keyof T, 'asc' | 'desc'][];

  return (a: T, b: T) => {
    for (const [key, direction] of entries) {
      const v1 = a[key];
      const v2 = b[key];
      const dir = direction === 'desc' ? -1 : 1;

      const cmp = compare(v1, v2);
      if (cmp !== 0) return cmp * dir;
    }

    return 0;
  };
};

Features

  • Isomorphic: Works in both Browser and Node.js.
  • Integrated Comparison: Uses the compare utility internally for reliable ordering.
  • Standard Interface: Returns a comparator compatible with native Array.prototype.sort().
  • Type-safe: Properly typed for objects and their selected properties.

API

ts
function compareBy<T>(selector: (item: T) => any): (a: T, b: T) => -1 | 0 | 1;

Parameters

  • selector: A function that receives an item and returns the value to be used for comparison.

Returns

  • A comparator function that takes two items (a, b) and returns -1, 0, or 1.

Examples

Sorting Objects by Property

ts
import { compareBy } from '@vielzeug/toolkit';

const users = [
  { name: 'Charlie', age: 35 },
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
];

// Create a comparator for the 'age' property
const byAge = compareBy((u) => u.age);

users.sort(byAge);
// Results in: Bob (25), Alice (30), Charlie (35)

Sorting with Computed Values

ts
import { compareBy } from '@vielzeug/toolkit';

const files = ['data.json', 'report.pdf', 'README.md'];

// Sort by extension length
const byExtLength = compareBy((f) => f.split('.').pop()?.length || 0);

files.sort(byExtLength);

Implementation Notes

  • Performance-optimized factory that pre-binds the selector.
  • Internally leverages compare to handle the logic for primitives.
  • Throws TypeError if selector is not a function.

See Also

  • compare: The underlying primitive comparison logic.
  • sort: Functional sorting using a selector directly.
  • sortBy: Sort by multiple fields.