js-natural-sort is a JavaScript package that provides a natural sorting function for strings and numbers, handling various types of data such as dates, IPs, hexadecimal numbers, and regular strings. It offers a more intuitive sorting order compared to default lexicographical sorting.
- Natural sorting (e.g. '10' < '100')
- Date-aware comparisons, for both date strings and
Dateobjects - IP address sorting (IPv4, and IPv6 in full uncompressed form)
- Hexadecimal value support, exact beyond
Number.MAX_SAFE_INTEGER - Case-insensitive mode
- Handles leading zeroes correctly
- Object support via key or accessor
- ESM, CommonJS, AMD, UMD (browser), and minified UMD build support
- TypeScript type definitions included
You can install the package via npm:
npm install @andreasnicolaou/js-natural-sortyarn add @andreasnicolaou/js-natural-sortpnpm add @andreasnicolaou/js-natural-sortFor direct browser usage without a build step:
<!-- unpkg CDN (latest version, unminified) -->
<script src="https://unpkg.com/@andreasnicolaou/js-natural-sort/dist/index.umd.js"></script>
<!-- unpkg CDN (latest version, minified) -->
<script src="https://unpkg.com/@andreasnicolaou/js-natural-sort/dist/index.umd.min.js"></script>
<!-- jsDelivr CDN (unminified) -->
<script src="https://cdn.jsdelivr.net/npm/@andreasnicolaou/js-natural-sort/dist/index.umd.js"></script>
<!-- jsDelivr CDN (minified) -->
<script src="https://cdn.jsdelivr.net/npm/@andreasnicolaou/js-natural-sort/dist/index.umd.min.js"></script>import { naturalSort } from '@andreasnicolaou/js-natural-sort';
const arr = ['10', '2', '1'].sort(naturalSort());
console.log(arr); // ['1', '2', '10']const { naturalSort } = require('@andreasnicolaou/js-natural-sort');
const arr = ['10', '2', '1'].sort(naturalSort());
console.log(arr); // ['1', '2', '10']<script src="https://unpkg.com/@andreasnicolaou/js-natural-sort/dist/index.umd.min.js"></script>
<script>
// global: naturalSort
const arr = ['10', '2', '1'].sort(naturalSort());
console.log(arr); // ['1', '2', '10']
</script>Note: When using the UMD build in the browser, the global variable is named
naturalSort.
<script type="module">
import { naturalSort } from 'https://cdn.jsdelivr.net/npm/@andreasnicolaou/js-natural-sort/dist/index.js';
const arr = ['10', '2', '1'].sort(naturalSort());
console.log(arr); // ['1', '2', '10']
</script>Type definitions are included out of the box:
import { naturalSort } from '@andreasnicolaou/js-natural-sort';
const arr: string[] = ['10', '2', '1'].sort(naturalSort());import { naturalSort } from '@andreasnicolaou/js-natural-sort';
const arrFloats = ['10.0401', 10.022, 10.042, '10.021999'].sort(naturalSort());
console.log(arrFloats); // ['10.021999', 10.022, '10.0401', 10.042]import { naturalSort } from '@andreasnicolaou/js-natural-sort';
const arrDates = ['2022-01-02', '2021-12-31', '2020-11-11', '2021-01-01'].sort(naturalSort());
console.log(arrDates); // ['2020-11-11', '2021-01-01', '2021-12-31', '2022-01-02']import { naturalSort } from '@andreasnicolaou/js-natural-sort';
const arrObj = [
{ name: 'John', age: 30 },
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 35 },
].sort(naturalSort({ key: (x) => `${x.name}${x.age}` }));
console.log(arrObj); // [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 35 }, { name: 'John', age: 30 }]import { naturalSort } from '@andreasnicolaou/js-natural-sort';
const arrObj2 = [{ id: 10 }, { id: 2 }, { id: 1 }].sort(naturalSort({ key: 'id', order: 'desc' }));
console.log(arrObj2); // [{ id: 10 }, { id: 2 }, { id: 1 }]Legacy outputs (dist/index.esm.js, dist/index.cjs.js, dist/index.amd.js) are still published for compatibility, but it is recommended to use the new outputs (dist/index.js, dist/index.cjs, UMD, and type definitions) for all new projects.
Note: The legacy AMD build (
dist/index.amd.js) exposes the global variable asnatural-sort(with a dash), notnaturalSort. This is for backward compatibility.
Type definitions are included. You can use this package with full TypeScript support out of the box.
The function accepts a single optional options object with the following properties:
| Parameter | Type | Description | Default |
|---|---|---|---|
insensitive |
boolean |
Whether the sorting should be case-insensitive. | false |
order |
'asc' | 'desc' |
Sorting order. Can be 'asc' or 'desc'. |
'asc' |
key |
keyof T | ((obj: T) => NaturalSortableValue) |
Key or accessor function to extract sortable value from item. | undefined |
Values are compared by splitting them into alternating text and number chunks, then comparing chunk by chunk:
- Within a chunk, numbers sort before text (
'2'before'apple') - Text is compared by character code, so uppercase precedes lowercase unless
insensitiveis set - A number with a leading zero keeps its padding and compares as text, so
file1sorts beforefile001. A value that is entirely one number is always numeric, so'0','007'and'0.5'compare by value - Two IP addresses of the same family compare part by part; an IPv4 and an IPv6 address fall back to natural ordering
nullandundefinedcompare as empty strings, which places them last in ascending order
Contributions are welcome! If you encounter issues or have ideas to enhance the library, feel free to submit an issue or pull request.