| [9af201e] | 1 | # String Natural Compare
|
|---|
| 2 |
|
|---|
| 3 | [](https://www.npmjs.com/package/string-natural-compare)
|
|---|
| 4 | [](https://travis-ci.org/nwoltman/string-natural-compare)
|
|---|
| 5 | [](https://coveralls.io/r/nwoltman/string-natural-compare?branch=master)
|
|---|
| 6 | [](https://david-dm.org/nwoltman/string-natural-compare)
|
|---|
| 7 |
|
|---|
| 8 | Compare alphanumeric strings the same way a human would, using a natural order algorithm (originally known as the [alphanum algorithm](http://davekoelle.com/alphanum.html)) where numeric characters are sorted based on their numeric values rather than their ASCII values.
|
|---|
| 9 |
|
|---|
| 10 | ```
|
|---|
| 11 | Standard sorting: Natural order sorting:
|
|---|
| 12 | img1.png img1.png
|
|---|
| 13 | img10.png img2.png
|
|---|
| 14 | img12.png img10.png
|
|---|
| 15 | img2.png img12.png
|
|---|
| 16 | ```
|
|---|
| 17 |
|
|---|
| 18 | This module exports a function that returns a number indicating whether one string should come before, after, or is the same as another string.
|
|---|
| 19 | It can be used directly with the native [`.sort()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) array method.
|
|---|
| 20 |
|
|---|
| 21 | ### Fast and Robust
|
|---|
| 22 |
|
|---|
| 23 | This module can compare strings containing any size of number and is heavily tested with a custom [benchmark suite](https://github.com/nwoltman/string-natural-compare/tree/master/benchmark) to make sure that it is as fast as possible.
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 | ## Installation
|
|---|
| 27 |
|
|---|
| 28 | ```sh
|
|---|
| 29 | npm install string-natural-compare --save
|
|---|
| 30 | # or
|
|---|
| 31 | yarn add string-natural-compare
|
|---|
| 32 | ```
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 | ## Usage
|
|---|
| 36 |
|
|---|
| 37 | #### `naturalCompare(strA, strB[, options])`
|
|---|
| 38 |
|
|---|
| 39 | + `strA` (_string_)
|
|---|
| 40 | + `strB` (_string_)
|
|---|
| 41 | + `options` (_object_) - Optional options object with the following options:
|
|---|
| 42 | + `caseInsensitive` (_boolean_) - Set to `true` to compare strings case-insensitively. Default: `false`.
|
|---|
| 43 | + `alphabet` (_string_) - A string of characters that define a custom character ordering. Default: `undefined`.
|
|---|
| 44 |
|
|---|
| 45 | ```js
|
|---|
| 46 | const naturalCompare = require('string-natural-compare');
|
|---|
| 47 |
|
|---|
| 48 | // Simple, case-sensitive sorting
|
|---|
| 49 | const files = ['z1.doc', 'z10.doc', 'z17.doc', 'z2.doc', 'z23.doc', 'z3.doc'];
|
|---|
| 50 | files.sort(naturalCompare);
|
|---|
| 51 | // -> ['z1.doc', 'z2.doc', 'z3.doc', 'z10.doc', 'z17.doc', 'z23.doc']
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 | // Case-insensitive sorting
|
|---|
| 55 | const chars = ['B', 'C', 'a', 'd'];
|
|---|
| 56 | const naturalCompareCI = (a, b) => naturalCompare(a, b, {caseInsensitive: true});
|
|---|
| 57 | chars.sort(naturalCompareCI);
|
|---|
| 58 | // -> ['a', 'B', 'C', 'd']
|
|---|
| 59 |
|
|---|
| 60 | // Note:
|
|---|
| 61 | ['a', 'A'].sort(naturalCompareCI); // -> ['a', 'A']
|
|---|
| 62 | ['A', 'a'].sort(naturalCompareCI); // -> ['A', 'a']
|
|---|
| 63 |
|
|---|
| 64 |
|
|---|
| 65 | // Compare strings containing large numbers
|
|---|
| 66 | naturalCompare(
|
|---|
| 67 | '1165874568735487968325787328996865',
|
|---|
| 68 | '265812277985321589735871687040841'
|
|---|
| 69 | );
|
|---|
| 70 | // -> 1
|
|---|
| 71 | // (Other inputs with the same ordering as this example may yield a different number > 0)
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 | // Sorting an array of objects
|
|---|
| 75 | const hotelRooms = [
|
|---|
| 76 | {street: '350 5th Ave', room: 'A-1021'},
|
|---|
| 77 | {street: '350 5th Ave', room: 'A-21046-b'}
|
|---|
| 78 | ];
|
|---|
| 79 | // Sort by street (case-insensitive), then by room (case-sensitive)
|
|---|
| 80 | hotelRooms.sort((a, b) => (
|
|---|
| 81 | naturalCompare(a.street, b.street, {caseInsensitive: true}) ||
|
|---|
| 82 | naturalCompare(a.room, b.room)
|
|---|
| 83 | ));
|
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 | // When text transformation is needed or when doing a case-insensitive sort on a
|
|---|
| 87 | // large array of objects, it is best for performance to pre-compute the
|
|---|
| 88 | // transformed text and store it on the object. This way, the text will not need
|
|---|
| 89 | // to be transformed for every comparison while sorting.
|
|---|
| 90 | const cars = [
|
|---|
| 91 | {make: 'Audi', model: 'R8'},
|
|---|
| 92 | {make: 'Porsche', model: '911 Turbo S'}
|
|---|
| 93 | ];
|
|---|
| 94 | // Sort by make, then by model (both case-insensitive)
|
|---|
| 95 | for (const car of cars) {
|
|---|
| 96 | car.sortKey = (car.make + ' ' + car.model).toLowerCase();
|
|---|
| 97 | }
|
|---|
| 98 | cars.sort((a, b) => naturalCompare(a.sortKey, b.sortKey));
|
|---|
| 99 |
|
|---|
| 100 |
|
|---|
| 101 | // Using a custom alphabet (Russian alphabet)
|
|---|
| 102 | const russianOpts = {
|
|---|
| 103 | alphabet: 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя',
|
|---|
| 104 | };
|
|---|
| 105 | ['Ё', 'А', 'б', 'Б'].sort((a, b) => naturalCompare(a, b, russianOpts));
|
|---|
| 106 | // -> ['А', 'Б', 'Ё', 'б']
|
|---|
| 107 | ```
|
|---|
| 108 |
|
|---|
| 109 | **Note:** Putting numbers in the custom alphabet can cause undefined behaviour.
|
|---|