Utils (@pim.sk/utils)

sortAssoc

Sorts an array of objects by one or more fields. Supports string, number, date and boolean comparison with configurable direction (asc / desc) and case sensitivity. Mutates the original array and returns it.
import sortAssoc from '@pim.sk/utils/sortAssoc.mjs'
Must be called with new:
ary = new sortAssoc( ary, 'field' )
Without new the function logs a warning and returns false.

Syntax

new sortAssoc( ary, 'field' )                              // asc, String (defaults)
new sortAssoc( ary, 'field', 'desc' )                      // direction
new sortAssoc( ary, 'field', 'asc', Number )               // type constructor
new sortAssoc( ary, 'field', 'asc', 'number' )             // type string alias
new sortAssoc( ary, 'field', 'asc', Number, true )         // case-sensitive
new sortAssoc( ary, { field, by, type, sensitive } )       // object syntax
new sortAssoc( ary, [ {field, by, type}, {...} ] )          // multi-sort array

Examples

sort by string — short syntax

Default type is String. Default direction is asc. Pass just the field name for the shortest form. Results are returned (array is sorted in place).

const data = [
    { name: "Banana" },
    { name: "apple"  },   // lowercase — case-insensitive by default
    { name: "Mango"  },
    { name: "cherry" },
]

new sortAssoc( data, "name" )
// asc  → apple, Banana, cherry, Mango
// desc → Mango, cherry, Banana, apple
const data = [
    { name: "Banana" }, { name: "apple" },
    { name: "Mango"  }, { name: "cherry" },
]

new sortAssoc( data, "name" )           // asc, String (defaults)
new sortAssoc( data, "name", "desc" )   // desc

sort by number — type: Number

Pass Number (constructor) or the string "number" as the type argument. Without it, price values would be compared as strings ("9" > "10").

const products = [
    { name: "Banana", price: 0.5  },
    { name: "Mango",  price: 2.5  },
    { name: "Apple",  price: 1.2  },
    { name: "Onion",  price: 0.4  },
    { name: "Pepper", price: 10.0 },  // "10" < "9" as string!
    { name: "Carrot", price: 9.0  },
]

new sortAssoc( data, "price", "asc", Number )
// → 0.4 · 0.5 · 1.2 · 2.5 · 9 · 10   (numeric order)
//   without Number → 0.4 · 0.5 · 1.2 · 10 · 2.5 · 9  (string order)
// correct — numeric comparison:
new sortAssoc( data, "price", "asc",  Number )
new sortAssoc( data, "price", "desc", Number )

// or use string alias:
new sortAssoc( data, { field: "price", by: "asc", type: "number" } )

// wrong — string comparison ("10" < "9"):
new sortAssoc( data, "price", "asc" )

sort by date — type: Date

Pass Date (constructor) or "date" as type. Strings like "2024-06-20" are parsed via new Date(). Useful for sorting logs, timestamps or ISO date fields.

const logs = [
    { event: "login",   created: "2024-03-15" },
    { event: "signup",  created: "2024-06-20" },
    { event: "update",  created: "2024-02-10" },
    { event: "logout",  created: "2024-01-02" },
]

new sortAssoc( logs, "created", "asc",  Date )
// oldest first  → 2024-01-02 · 2024-02-10 · 2024-03-15 · 2024-06-20

new sortAssoc( logs, "created", "desc", Date )
// newest first  → 2024-06-20 · 2024-03-15 · 2024-02-10 · 2024-01-02
new sortAssoc( logs, "created", "asc",  Date )   // oldest first
new sortAssoc( logs, "created", "desc", Date )   // newest first

// object syntax:
new sortAssoc( logs, { field: "created", by: "desc", type: Date } )

object syntax — full options with sensitive

Pass an options object (or array of objects for multi-sort) with explicit field, by, type and sensitive keys. All keys are optional — missing ones use defaults (type: String, by: "asc", sensitive: false).

// object syntax — equivalent to shorthand:
new sortAssoc( data, { field: "name", by: "desc", type: String } )

// case-sensitive: "Apple" before "banana" (uppercase sorts before lowercase)
new sortAssoc( data, { field: "name", by: "asc", sensitive: true } )

// sensitive: false (default) — case-insensitive
new sortAssoc( data, { field: "name", by: "asc", sensitive: false } )
// sensitive: false — case-insensitive (default)
new sortAssoc( data, { field: "name", by: "asc", sensitive: false } )
// → Apple, apple, Banana, banana, Mango

// sensitive: true — uppercase letters sort before lowercase (ASCII order)
new sortAssoc( data, { field: "name", by: "asc", sensitive: true } )
// → Apple, Banana, Mango, apple, banana

multi-field sort — array of conditions

Pass an array of option objects to sort by multiple fields. The first condition is primary — when values are equal, the next condition is applied as a tiebreaker.

const items = [
    { name: "Banana", category: "fruit",     price: 0.5 },
    { name: "Mango",  category: "fruit",     price: 2.5 },
    { name: "Onion",  category: "vegetable", price: 0.4 },
    { name: "Apple",  category: "fruit",     price: 1.2 },
    { name: "Pepper", category: "vegetable", price: 1.5 },
    { name: "Carrot", category: "vegetable", price: 0.8 },
]

// primary: category asc  →  secondary: price desc
new sortAssoc( items, [
    { field: "category", by: "asc",  type: String },
    { field: "price",    by: "desc", type: Number },
])
// fruit     → Mango (2.5) · Apple (1.2) · Banana (0.5)
// vegetable → Pepper(1.5) · Carrot(0.8) · Onion (0.4)
new sortAssoc( items, [
    { field: "category", by: "asc",  type: String },
    { field: "price",    by: "desc", type: Number },
])

new sortAssoc( items, [
    { field: "category", by: "asc",  type: String },
    { field: "price",    by: "asc",  type: Number },
])

new sortAssoc( items, [
    { field: "category", by: "desc", type: String },
    { field: "name",     by: "asc",  type: String },
])
v 1.1.2