Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
natural-orderby
Advanced tools
Lightweight and performant natural sorting of arrays and collections by differentiating between unicode characters, numbers, dates, etc.
The natural-orderby package is a utility for sorting arrays of strings or objects in a natural order, which means it sorts based on human-friendly sorting rules rather than strict lexicographical order. This is particularly useful for sorting strings that contain numbers, as it will sort them in a way that is more intuitive to humans.
Sorting an array of strings
Sorts an array of strings containing numbers in a natural order, so that 'a2' comes before 'a12'.
["a1", "a12", "a2"].sort(compare())
Sorting an array of objects
Sorts an array of objects based on the specified object key in a natural order.
objects.sort(compareOn(obj => obj.key))
Sorting with a custom accessor
Sorts an array of objects with a custom accessor, such as converting a date string to a Date object before sorting.
objects.sort(compareOn(obj => obj.date, { accessor: date => new Date(date) }))
Alphanum-sort is an npm package that provides a similar functionality to natural-orderby. It offers alphanumeric sorting, which is useful for sorting strings with a mix of letters and numbers. Compared to natural-orderby, it may have different customization options and sorting behavior.
String-natural-compare is another npm package that allows for natural order sorting of strings. It is designed to compare two strings directly rather than sorting an entire array. This package might be more lightweight than natural-orderby but with less built-in functionality for sorting arrays.
Lightweight (~1.7kB gzipped) and performant natural sorting of arrays and collections by differentiating between unicode characters, numbers, dates, etc.
People sort strings containing numbers differently than most sorting algorithms, which sort values by comparing strings in Unicode code point order. This produces an ordering that is inconsistent with human logic.
natural-orderby
sorts the primitive values of Boolean
, Null
, Undefined
, Number
or String
type as well as Date
objects. When comparing strings it differentiates between unicode characters, integer, floating as well as hexadecimal numbers, various date formats, etc. You may sort flat or nested arrays or arrays of objects in a natural sorting order using natural-orderby
.
In addition to the efficient and fast orderBy()
method natural-orderby
also provides the method compare()
, which may be passed to Array.prototype.sort()
.
# npm
npm install natural-orderby --save
# yarn
yarn add natural-orderby
If you´re not using a module bundler or package manager there´s also a global ("IIFE") build hosted on the unpkg CDN. Simply add the following <script>
tag to the bottom of your HTML file:
<script src="https://unpkg.com/natural-orderby/dist/natural-orderby.min.js"></script>
Once you've added natural-orderby
you will have access to the global window.naturalOrderBy
variable.
// Using ES modules
import { orderBy } from 'natural-orderby';
// Using CommonJS modules
// const { orderBy } = require('natural-orderby');
const users = [
{
username: 'Bamm-Bamm',
ip: '192.168.5.2',
datetime: 'Fri Jun 15 2018 16:48:00 GMT+0200 (CEST)'
},
{
username: 'Wilma',
ip: '192.168.10.1',
datetime: '14 Jun 2018 00:00:00 PDT'
},
{
username: 'Dino',
ip: '192.168.0.2',
datetime: 'June 15, 2018 14:48:00'
},
{
username: 'Barney',
ip: '192.168.1.1',
datetime: 'Thu, 14 Jun 2018 07:00:00 GMT'
},
{
username: 'Pebbles',
ip: '192.168.1.21',
datetime: '15 June 2018 14:48 UTC'
},
{
username: 'Hoppy',
ip: '192.168.5.10',
datetime: '2018-06-15T14:48:00.000Z'
},
];
const sortedUsers = orderBy(
users,
[v => v.datetime, v => v.ip],
['desc', 'asc']
);
This is the return value of orderBy()
:
[
{
username: 'Dino',
ip: '192.168.0.2',
datetime: 'June 15, 2018 14:48:00',
},
{
username: 'Pebbles',
ip: '192.168.1.21',
datetime: '15 June 2018 14:48 UTC',
},
{
username: 'Bamm-Bamm',
ip: '192.168.5.2',
datetime: 'Fri Jun 15 2018 16:48:00 GMT+0200 (CEST)',
},
{
username: 'Hoppy',
ip: '192.168.5.10',
datetime: '2018-06-15T14:48:00.000Z',
},
{
username: 'Barney',
ip: '192.168.1.1',
datetime: 'Thu, 14 Jun 2018 07:00:00 GMT',
},
{
username: 'Wilma',
ip: '192.168.10.1',
datetime: '14 Jun 2018 00:00:00 PDT',
},
];
orderBy()
Creates an array of elements, natural sorted by specified identifiers
and the corresponding sort orders
. This method implements a stable sort algorithm, which means the original sort order of equal elements is preserved.
It also avoids the high overhead caused by Array.prototype.sort()
invoking a compare function multiple times per element within the array.
orderBy<T>(
collection: Array<T>,
identifiers?: ?Array<Identifier<T>> | ?Identifier<T>,
orders?: ?Array<Order> | ?Order
): Array<T>
Type | Value |
---|---|
Identifier<T> | string | (value: T) => mixed) |
Order | 'asc' | 'desc' | (valueA: mixed, valueB: mixed) => number |
orderBy()
sorts the elements of an array by specified identifiers and the corresponding sort orders in a natural order and returns a new array containing the sorted elements.
If collection
is an array of primitives, identifiers
may be unspecified. Otherwise, you should specify identifiers
to sort by or collection
will be returned unsorted. An identifier can beexpressed by:
collection
is a nested array,collection
is an array of objects,collection
.If orders
is unspecified, all values are sorted in ascending order. Otherwise, specify an order of 'desc'
for descending or 'asc'
for ascending sort order of corresponding values. You may also specify a compare function for an order, which will be invoked by two arguments: (valueA, valueB)
. It must return a number representing the sort order.
Note:
orderBy()
always returns a new array, even if the original was already sorted.
import { orderBy } from 'natural-orderby';
// Simple numerics
orderBy(['10', 9, 2, '1', '4']);
// => ['1', 2, '4', 9, '10']
// Floats
orderBy(['10.0401', 10.022, 10.042, '10.021999']);
// => ['10.021999', 10.022, '10.0401', 10.042]
// Float & decimal notation
orderBy(['10.04f', '10.039F', '10.038d', '10.037D']);
// => ['10.037D', '10.038d', '10.039F', '10.04f']
// Scientific notation
orderBy(['1.528535047e5', '1.528535047e7', '1.528535047e3']);
// => ['1.528535047e3', '1.528535047e5', '1.528535047e7']
// IP addresses
orderBy(['192.168.201.100', '192.168.201.12', '192.168.21.1']);
// => ['192.168.21.1', '192.168.201.12', '192.168.21.100']
// Filenames
orderBy(['01asset_0815.png', 'asset_47103.jpg', 'asset_151.jpg', '001asset_4711.jpg', 'asset_342.mp4']);
// => ['001asset_4711.jpg', '01asset_0815.png', 'asset_151.jpg', 'asset_342.mp4', 'asset_47103.jpg']
// Filenames - ordered by extension and filename
orderBy(
['01asset_0815.png', 'asset_47103.jpg', 'asset_151.jpg', '001asset_4711.jpg', 'asset_342.mp4'],[v => v.split('.').pop(), v => v]
);
// => ['001asset_4711.jpg', 'asset_151.jpg', 'asset_47103.jpg', 'asset_342.mp4', '01asset_0815.png']
// Dates
orderBy(['10/12/2018', '10/11/2018', '10/11/2017', '10/12/2017']);
// => ['10/11/2017', '10/12/2017', '10/11/2018', '10/12/2018']
orderBy(['Thu, 15 Jun 2017 20:45:30 GMT', 'Thu, 3 May 2018 17:45:30 GMT', 'Thu, 15 Jun 2017 17:45:30 GMT']);
// => ['Thu, 15 Jun 2017 17:45:30 GMT', 'Thu, 15 Jun 2018 20:45:30 GMT', 'Thu, 3 May 2018 17:45:30 GMT']
// Money
orderBy(['$102.00', '$21.10', '$101.02', '$101.01']);
// => ['$21.10', '$101.01', '$101.02', '$102.00']
// Default sort order case-sensitive
orderBy(['A', 'b', 'C', 'd', 'E', 'f']);
// => ['A', 'C', 'E', 'b', 'd', 'f']
// Enabled case-insensitive sort order
orderBy(['A', 'C', 'E', 'b', 'd', 'f'], [v => v.toLowerCase()]);
// => ['A', 'b', 'C', 'd', 'E', 'f']
// Default ascending sort order
orderBy(['a', 'c', 'f', 'd', 'e', 'b']);
// => ['a', 'b', 'c', 'd', 'e', 'f']
// Descending sort order
orderBy(['a', 'c', 'f', 'd', 'e', 'b'], null, ['desc']);
// => ['f', 'e', 'd', 'c', 'b', 'a']
// Custom compare function
orderBy([2, 1, 5, 8, 6, 9], null, [(valueA, valueB) => valueA - valueB]);
// => [1, 2, 5, 6, 8, 9]
// collections
const users = [
{
username: 'Bamm-Bamm',
ip: '192.168.5.2',
datetime: 'Fri Jun 15 2018 16:48:00 GMT+0200 (CEST)'
},
{
username: 'Wilma',
ip: '192.168.10.1',
datetime: '14 Jun 2018 00:00:00 PDT'
},
{
username: 'Dino',
ip: '192.168.0.2',
datetime: 'June 15, 2018 14:48:00'
},
{
username: 'Barney',
ip: '192.168.1.1',
datetime: 'Thu, 14 Jun 2018 07:00:00 GMT'
},
{
username: 'Pebbles',
ip: '192.168.1.21',
datetime: '15 June 2018 14:48 UTC'
},
{
username: 'Hoppy',
ip: '192.168.5.10',
datetime: '2018-06-15T14:48:00.000Z'
},
];
orderBy(
users,
[v => v.datetime, v => v.ip],
['desc', 'asc']
);
// => [
// {
// username: 'Dino',
// ip: '192.168.0.2',
// datetime: 'June 15, 2018 14:48:00',
// },
// {
// username: 'Pebbles',
// ip: '192.168.1.21',
// datetime: '15 June 2018 14:48 UTC',
// },
// {
// username: 'Bamm-Bamm',
// ip: '192.168.5.2',
// datetime: 'Fri Jun 15 2018 16:48:00 GMT+0200 (CEST)',
// },
// {
// username: 'Hoppy',
// ip: '192.168.5.10',
// datetime: '2018-06-15T14:48:00.000Z',
// },
// {
// username: 'Barney',
// ip: '192.168.1.1',
// datetime: 'Thu, 14 Jun 2018 07:00:00 GMT',
// },
// {
// username: 'Wilma',
// ip: '192.168.10.1',
// datetime: '14 Jun 2018 00:00:00 PDT',
// },
// ]
compare()
Creates a compare function that defines the natural sort order and which may be passed to Array.prototype.sort()
.
compare(options?: CompareOptions): CompareFn
Type | Value |
---|---|
CompareOptions | { caseSensitive?: boolean, order?: 'asc' | 'desc' } |
CompareFn | (valueA: mixed, valueB: mixed) => number |
compare()
returns a compare function that defines the natural sort order and which may be passed to Array.prototype.sort()
.
If options
or its property caseSensitive
is unspecified, values are sorted case sensitive. Otherwise, specify true
for case sensitive or false
for case insensitive sorting.
If options
or its property order
is unspecified, values are sorted in ascending sort order. Otherwise, specify an order of 'desc'
for descending or 'asc'
for ascending sort order of values.
import { compare } from 'natural-orderby';
// Simple numerics
['10', 9, 2, '1', '4'].sort(compare());
// => ['1', 2, '4', 9, '10']
// Floats
['10.0401', 10.022, 10.042, '10.021999'].sort(compare());
// => ['10.021999', 10.022, '10.0401', 10.042]
// Float & decimal notation
['10.04f', '10.039F', '10.038d', '10.037D'].sort(compare());
// => ['10.037D', '10.038d', '10.039F', '10.04f']
// Scientific notation
['1.528535047e5', '1.528535047e7', '1.528535047e3'].sort(compare());
// => ['1.528535047e3', '1.528535047e5', '1.528535047e7']
// IP addresses
['192.168.201.100', '192.168.201.12', '192.168.21.1'].sort(compare());
// => ['192.168.21.1', '192.168.201.12', '192.168.21.100']
// Filenames
['01asset_0815.jpg', 'asset_47103.jpg', 'asset_151.jpg', '001asset_4711.jpg', 'asset_342.mp4'].sort(compare());
// => ['001asset_4711.jpg', '01asset_0815.jpg', 'asset_151.jpg', 'asset_342.mp4', 'asset_47103.jpg']
// Dates
['10/12/2018', '10/11/2018', '10/11/2017', '10/12/2017'].sort(compare());
// => ['10/11/2017', '10/12/2017', '10/11/2018', '10/12/2018']
['Thu, 15 Jun 2017 20:45:30 GMT', 'Thu, 3 May 2018 17:45:30 GMT', 'Thu, 15 Jun 2017 17:45:30 GMT'].sort(compare());
// => ['Thu, 15 Jun 2017 17:45:30 GMT', 'Thu, 15 Jun 2018 20:45:30 GMT', 'Thu, 3 May 2018 17:45:30 GMT']
// Money
['$102.00', '$21.10', '$101.02', '$101.01'].sort(compare());
// => ['$21.10', '$101.01', '$101.02', '$102.00']
// Default sort order case-sensitive
['A', 'b', 'C', 'd', 'E', 'f'].sort(compare());
// => ['A', 'C', 'E', 'b', 'd', 'f']
// Enabled case-insensitive sort order
['A', 'C', 'E', 'b', 'd', 'f'].sort(compare({ caseSensitive: false }));
// => ['A', 'b', 'C', 'd', 'E', 'f']
// Default ascending sort order
['a', 'c', 'f', 'd', 'e', 'b'].sort(compare());
// => ['a', 'b', 'c', 'd', 'e', 'f']
// Descending sort order
['a', 'c', 'f', 'd', 'e', 'b'].sort(compare({ order: 'desc' }));
// => ['f', 'e', 'd', 'c', 'b', 'a']
// collections
const users = [
{
username: 'Bamm-Bamm',
lastLogin: {
ip: '192.168.5.2',
datetime: 'Fri Jun 15 2018 16:48:00 GMT+0200 (CEST)'
},
},
{
username: 'Wilma',
lastLogin: {
ip: '192.168.10.1',
datetime: '14 Jun 2018 00:00:00 PDT'
},
},
{
username: 'Dino',
lastLogin: {
ip: '192.168.0.2',
datetime: 'June 15, 2018 14:48:00'
},
},
{
username: 'Barney',
lastLogin: {
ip: '192.168.1.1',
datetime: 'Thu, 14 Jun 2018 07:00:00 GMT'
},
},
{
username: 'Pebbles',
lastLogin: {
ip: '192.168.1.21',
datetime: '15 June 2018 14:48 UTC'
},
},
{
username: 'Hoppy',
lastLogin: {
ip: '192.168.5.10',
datetime: '2018-06-15T14:48:00.000Z'
},
},
];
users.sort((a, b) => compare()(a.lastLogin.ip, b.lastLogin.ip));
// => [
// {
// username: 'Dino',
// lastLogin: {
// ip: '192.168.0.2',
// datetime: 'June 15, 2018 14:48:00'
// },
// },
// {
// username: 'Barney',
// lastLogin: {
// ip: '192.168.1.1',
// datetime: 'Thu, 14 Jun 2018 07:00:00 GMT'
// },
// },
// {
// username: 'Pebbles',
// lastLogin: {
// ip: '192.168.1.21',
// datetime: '15 June 2018 14:48 UTC'
// },
// },
// {
// username: 'Bamm-Bamm',
// lastLogin: {
// ip: '192.168.5.2',
// datetime: 'Fri Jun 15 2018 16:48:00 GMT+0200 (CEST)'
// },
// },
// {
// username: 'Hoppy',
// lastLogin: {
// ip: '192.168.5.10',
// datetime: '2018-06-15T14:48:00.000Z'
// },
// },
// {
// username: 'Wilma',
// lastLogin: {
// ip: '192.168.10.1',
// datetime: '14 Jun 2018 00:00:00 PDT'
// },
// },
// ]
natural-orderby
has first-class Flow support with zero configuration to assist you in finding type errors while using our modules.
Inspired by The Alphanum Algorithm from Dave Koelle.
Licensed under the MIT License, Copyright © 2018 Olaf Ennen.
See LICENSE for more information.
FAQs
Lightweight and performant natural sorting of arrays and collections by differentiating between unicode characters, numbers, dates, etc.
The npm package natural-orderby receives a total of 924,535 weekly downloads. As such, natural-orderby popularity was classified as popular.
We found that natural-orderby demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.