diff --git a/lib/expression/docs/function/relational/compareNatural.js b/lib/expression/docs/function/relational/compareNatural.js index f750b79ba..74a4b89dd 100644 --- a/lib/expression/docs/function/relational/compareNatural.js +++ b/lib/expression/docs/function/relational/compareNatural.js @@ -5,7 +5,7 @@ module.exports = { 'compareNatural(x, y)' ], 'description': - 'Compare two values in a natural way. For numeric values, returns 1 if x is larger than y, -1 if x is smaller than y, and 0 if x and y are equal. Strings and complex numbers are compared in a natural way.', + 'Compare two values in a natural way.', 'examples': [ 'compare(2, 3)', 'compare(3, 2)', diff --git a/lib/function/matrix/sort.js b/lib/function/matrix/sort.js index 892f0b259..799fa095f 100644 --- a/lib/function/matrix/sort.js +++ b/lib/function/matrix/sort.js @@ -8,7 +8,7 @@ function factory (type, config, load, typed) { var compareDesc = function (a, b) { return -compareAsc(a, b); }; - var deepStrictCompare = load(require('../relational/deepStrictCompare')); + var compareNatural = load(require('../relational/compareNatural')); /** * Sort the items in a matrix. @@ -33,7 +33,7 @@ function factory (type, config, load, typed) { * filter, forEach, map, compare, compareNatural * * @param {Matrix | Array} x A one dimensional matrix or array to sort - * @param {Function | 'asc' | 'desc' | 'deep'} [compare='asc'] + * @param {Function | 'asc' | 'desc' | 'natural'} [compare='asc'] * An optional _comparator function or name. The function is called as * `compare(a, b)`, and must return 1 when a > b, -1 when a < b, * and 0 when a == b. @@ -74,8 +74,8 @@ function factory (type, config, load, typed) { sort.toTex = undefined; // use default template /** - * Get the comparator for given order ('asc', 'desc', 'deep') - * @param {'asc' | 'desc' | 'deep'} order + * Get the comparator for given order ('asc', 'desc', 'natural') + * @param {'asc' | 'desc' | 'natural'} order * @return {Function} Returns a _comparator function */ function _comparator (order) { @@ -85,11 +85,11 @@ function factory (type, config, load, typed) { else if (order === 'desc') { return compareDesc; } - else if (order === 'deep') { - return deepStrictCompare; + else if (order === 'natural') { + return compareNatural; } else { - throw new Error('String "asc", "desc", or "deep" expected'); + throw new Error('String "asc", "desc", or "natural" expected'); } } diff --git a/lib/function/relational/deepStrictCompare.js b/lib/function/relational/compareNatural.js similarity index 82% rename from lib/function/relational/deepStrictCompare.js rename to lib/function/relational/compareNatural.js index 428e290ad..6ed78ea9e 100644 --- a/lib/function/relational/deepStrictCompare.js +++ b/lib/function/relational/compareNatural.js @@ -1,9 +1,11 @@ 'use strict'; +var naturalSort = require('javascript-natural-sort'); var isCollection = require('../../utils/collection/isCollection'); function factory (type, config, load, typed) { var getTypeOf = load(require('../utils/typeof')); + var isNumeric = load(require('../utils/isNumeric')); var matrix = load(require('../../type/matrix/function/matrix')); var compare = load(require('./compare')); @@ -30,24 +32,24 @@ function factory (type, config, load, typed) { * * Syntax: * - * math.deepStrictCompare(x, y) + * math.compareNatural(x, y) * * Examples: * - * math.deepStrictCompare(6, 1); // returns 1 - * math.deepStrictCompare(2, 3); // returns -1 - * math.deepStrictCompare(7, 7); // returns 0 + * math.compareNatural(6, 1); // returns 1 + * math.compareNatural(2, 3); // returns -1 + * math.compareNatural(7, 7); // returns 0 * * var a = math.unit('5 cm'); * var b = math.unit('40 mm'); - * math.deepStrictCompare(a, b); // returns 1 + * math.compareNatural(a, b); // returns 1 * * var c = math.complex('2 + 3i'); * var d = math.complex('2 + 4i'); - * math.deepStrictCompare(c, d); // returns -1 + * math.compareNatural(c, d); // returns -1 * - * math.deepStrictCompare([1, 2, 3], [1, 2]); // returns 1 - * math.deepStrictCompare([1, 2], [1, 2]); // returns 0 + * math.compareNatural([1, 2, 3], [1, 2]); // returns 1 + * math.compareNatural([1, 2], [1, 2]); // returns 0 * * See also: * @@ -57,7 +59,7 @@ function factory (type, config, load, typed) { * @param {*} y Second value to compare * @return {number} Returns the result of the comparison: 1, 0 or -1. */ - var deepStrictCompare = typed('deepStrictCompare', { + var compareNatural = typed('compareNatural', { 'any, any': function (x, y) { var typeX = getTypeOf(x); var typeY = getTypeOf(y); @@ -65,9 +67,11 @@ function factory (type, config, load, typed) { // in case of different types, order by name of type // i.e. 'BigNumber' < 'Complex' if (typeX !== typeY) { - return compareString(typeX, typeY); + return naturalSort(typeX, typeY); } + // FIXME: compare all numeric types first by value and then by type + if (typeX === 'number') { return compareNumbers(x, y); } @@ -77,7 +81,7 @@ function factory (type, config, load, typed) { } if (typeX === 'Fraction') { - return compareFractions(x, y); + return compareFractions(x, y).valueOf(); } if (typeX === 'Complex') { @@ -85,8 +89,12 @@ function factory (type, config, load, typed) { } if (typeX === 'Unit') { - // FIXME: implement ordering for units with different base - return compareUnits(x, y); + if (x.equalBase(y)) { + return compareNatural(x.value, y.value); + } + + // compare by units + return compareArrays(x.formatUnits(), y.formatUnits()); } if (typeX === 'boolean') { @@ -94,13 +102,14 @@ function factory (type, config, load, typed) { } if (typeX === 'string') { - return compareString(x, y); + return naturalSort(x, y); } + // FIXME: compare matrices and arrays first by their values and then by type if (typeX === 'Matrix') { // can be SparseMatrix or DenseMatrix if (x.type !== y.type) { - return compareString(x.type, y.type) + return naturalSort(x.type, y.type) } if (x.type === 'DenseMatrix') { return compareDenseMatrices(x, y); @@ -131,7 +140,7 @@ function factory (type, config, load, typed) { } }); - deepStrictCompare.toTex = undefined; // use default template + compareNatural.toTex = undefined; // use default template /** * Compare two Arrays @@ -150,7 +159,7 @@ function factory (type, config, load, typed) { // compare each value for (var i = 0; i < a.length; i++) { - var v = deepStrictCompare(a[i], b[i]); + var v = compareNatural(a[i], b[i]); if (v !== 0) { return v; } @@ -230,8 +239,8 @@ function factory (type, config, load, typed) { if (keysA.length < keysB.length) { return -1; } // compare keys - keysA.sort(compareString) - keysB.sort(compareString) + keysA.sort(naturalSort) + keysB.sort(naturalSort) var c = compareArrays(keysA, keysB); if (c !== 0) { return c; @@ -239,7 +248,7 @@ function factory (type, config, load, typed) { // compare values for (var i = 0; i < keysA.length; i++) { - var v = deepStrictCompare(a[keysA[i]], b[keysB[i]]); + var v = compareNatural(a[keysA[i]], b[keysB[i]]); if (v !== 0) { return v; } @@ -248,17 +257,7 @@ function factory (type, config, load, typed) { return 0; } - return deepStrictCompare; -} - -/** - * Compare two strings by the char code of their characters - * @param {string} a - * @param {string} b - * @return {number} - */ -function compareString (a, b) { - return a > b ? 1 : a < b ? -1 : 0; + return compareNatural; } /** @@ -286,5 +285,5 @@ function compareComplexNumbers (a, b) { return 0; } -exports.name = 'deepStrictCompare'; +exports.name = 'compareNatural'; exports.factory = factory; diff --git a/lib/function/relational/index.js b/lib/function/relational/index.js index c894edf8f..56b1a8d42 100644 --- a/lib/function/relational/index.js +++ b/lib/function/relational/index.js @@ -1,6 +1,6 @@ module.exports = [ require('./compare'), - require('./deepStrictCompare'), + require('./compareNatural'), require('./deepEqual'), require('./equal'), require('./larger'), diff --git a/lib/function/set/setCartesian.js b/lib/function/set/setCartesian.js index 61ed78ff0..1250712a2 100644 --- a/lib/function/set/setCartesian.js +++ b/lib/function/set/setCartesian.js @@ -7,7 +7,7 @@ function factory (type, config, load, typed) { var matrix = load(require('../../type/matrix/DenseMatrix')); var size = load(require('../matrix/size')); var subset = load(require('../matrix/subset')); - var deepStrictCompare = load(require('../relational/deepStrictCompare')); + var compareNatural = load(require('../relational/compareNatural')); /** * Create the cartesian product of two (multi)sets. @@ -35,8 +35,8 @@ function factory (type, config, load, typed) { var result = []; } else { - var b1 = flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(deepStrictCompare); - var b2 = flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(deepStrictCompare); + var b1 = flatten(Array.isArray(a1) ? a1 : a1.toArray()).sort(compareNatural); + var b2 = flatten(Array.isArray(a2) ? a2 : a2.toArray()).sort(compareNatural); var result = []; for (var i=0; i