File Exchange

image thumbnail

Customizable Natural-Order Sort

version 2.1.2 (16.9 KB) by Stephen Cobeldick
Alphanumeric sort of a cell array of strings, with customizable numeric format.

45 Downloads

Updated 27 Nov 2020

View Version History

View License

Editor's Note: This file was selected as MATLAB Central Pick of the Week

To sort filenames or filepaths use NATSORTFILES:
http://www.mathworks.com/matlabcentral/fileexchange/47434-natural-order-filename-sort
To sort the rows of a cell array of strings use NATSORTROWS:
http://www.mathworks.com/matlabcentral/fileexchange/47433-natural-order-row-sort

### Summary ###

Alphanumeric sort of a cell array of strings (1xN char). Sorts the strings taking into account the values of any number substrings occurring within those strings. Compare for example:

X = {'a2', 'a10', 'a1'};
sort(X)
ans = 'a1' 'a10' 'a2'
natsort(X)
ans = 'a1' 'a2' 'a10'

By default NATSORT interprets all consecutive digits as integer numbers, the number substring recognition can be specified using a regular expression, allowing the number substrings to have:
* a +/- sign
* a decimal point and decimal fraction
* E-notation exponent
* decimal, octal, hexadecimal or binary notation
* Inf or NaN values
* criteria supported by regular expressions: look-arounds, quantifiers, etc.

And of course the sorting itself can also be controlled:
* ascending/descending sort direction
* character case sensitivity/insensitivity
* relative order of numbers vs. characters
* relative order of numbers vs NaNs

### Examples ###

%% Multiple integers (e.g. release version numbers):
>> A = {'v10.6', 'v9.10', 'v9.5', 'v10.10', 'v9.10.20', 'v9.10.8'};
>> sort(A)
ans = 'v10.10' 'v10.6' 'v9.10' 'v9.10.20' 'v9.10.8' 'v9.5'
>> natsort(A)
ans = 'v9.5' 'v9.10' 'v9.10.8' 'v9.10.20' 'v10.6' 'v10.10'

%% Integer, decimal, NaN, or Inf numbers, possibly with +/- signs:
>> B = {'test+NaN', 'test11.5', 'test-1.4', 'test', 'test-Inf', 'test+0.3'};
>> sort(B)
ans = 'test' 'test+0.3' 'test+NaN' 'test-1.4' 'test-Inf' 'test11.5'
>> natsort(B, '[-+]?(NaN|Inf|\d+\.?\d*)')
ans = 'test' 'test-Inf' 'test-1.4' 'test+0.3' 'test11.5' 'test+NaN'

%% Integer or decimal numbers, possibly with an exponent:
>> C = {'0.56e007', '', '43E-2', '10000', '9.8'};
>> sort(C)
ans = '' '0.56e007' '10000' '43E-2' '9.8'
>> natsort(C, '\d+\.?\d*([eE][-+]?\d+)?')
ans = '' '43E-2' '9.8' '10000' '0.56e007'

%% Hexadecimal numbers (with '0X' prefix):
>> D = {'a0X7C4z', 'a0X5z', 'a0X18z', 'a0XFz'};
>> sort(D)
ans = 'a0X18z' 'a0X5z' 'a0X7C4z' 'a0XFz'
>> natsort(D, '0X[0-9A-F]+', '%i')
ans = 'a0X5z' 'a0XFz' 'a0X18z' 'a0X7C4z'

%% Binary numbers:
>> E = {'a11111000100z', 'a101z', 'a000000000011000z', 'a1111z'};
>> sort(E)
ans = 'a000000000011000z' 'a101z' 'a11111000100z' 'a1111z'
>> natsort(E, '[01]+', '%b')
ans = 'a101z' 'a1111z' 'a000000000011000z' 'a11111000100z'

%% Case sensitivity:
>> F = {'a2', 'A20', 'A1', 'a10', 'A2', 'a1'};
>> natsort(F, [], 'ignorecase') % default
ans = 'A1' 'a1' 'a2' 'A2' 'a10' 'A20'
>> natsort(F, [], 'matchcase')
ans = 'A1' 'A2' 'A20' 'a1' 'a2' 'a10'

%% Sort order:
>> G = {'2', 'a', '', '3', 'B', '1'};
>> natsort(G, [], 'ascend') % default
ans = '' '1' '2' '3' 'a' 'B'
>> natsort(G, [], 'descend')
ans = 'B' 'a' '3' '2' '1' ''
>> natsort(G, [], 'num<char') % default
ans = '' '1' '2' '3' 'a' 'B'
>> natsort(G, [], 'char<num')
ans = '' 'a' 'B' '1' '2' '3'

%% UINT64 numbers (with full precision):
>> natsort({'a18446744073709551615z', 'a18446744073709551614z'}, [], '%lu')
ans = 'a18446744073709551614z' 'a18446744073709551615z'

Cite As

Stephen Cobeldick (2020). Customizable Natural-Order Sort (https://www.mathworks.com/matlabcentral/fileexchange/34464-customizable-natural-order-sort), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (12)

Emmanuel Osikpa

This is extremely helpful, thanks. Feels beyond natural

Jorge Viamontes

it works thank you so much for doing this saved me a lot of time to program it myself

Thank you, it is very useful! It is as the natsort of Python.

Chang hsiung

Save me days of programming. Got this going in 1 minute.

Xiaohui Gu

Very useful!

Stephen Cobeldick

@Akim Borbuev: the function NATSORT will parse all of the input cell array, so if you only want to sort by the first column then you can use indexing to select just that column, e.g. given an nx2 cell array C:

[~,idx] = natsort(C(:,1));
D = C(idx,:);

I then used the second output from NATSORT to sort the rows of the cell array. Does that do what you want?

Akim Borbuev

Hello,

I have a nx2 cell which I would like to apply your natural order sort to the first column but with respective values in the second column. Is it possible?
Thank you.

Regards,
Akim

Jan van den Broecke

Junjie Wang

qiap chen

It's good tool

Chang hsiung

MATLAB Release Compatibility
Created with R2010b
Compatible with any release
Platform Compatibility
Windows macOS Linux

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!