diff --git a/src/core/operations/SeqUtils.js b/src/core/operations/SeqUtils.js index 96fae0aa..70207e00 100755 --- a/src/core/operations/SeqUtils.js +++ b/src/core/operations/SeqUtils.js @@ -26,7 +26,7 @@ const SeqUtils = { * @constant * @default */ - SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address"], + SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"], /** * Sort operation. @@ -47,6 +47,8 @@ const SeqUtils = { sorted = sorted.sort(SeqUtils._caseInsensitiveSort); } else if (order === "IP address") { sorted = sorted.sort(SeqUtils._ipSort); + } else if (order === "Numeric") { + sorted = sorted.sort(SeqUtils._numericSort); } if (sortReverse) sorted.reverse(); @@ -221,6 +223,35 @@ const SeqUtils = { return a_ - b_; }, + + /** + * Comparison operation for sorting of numeric values. + * + * @author Chris van Marle + * @private + * @param {string} a + * @param {string} b + * @returns {number} + */ + _numericSort: function _numericSort(a, b) { + let a_ = a.split(/([^\d]+)/), + b_ = b.split(/([^\d]+)/); + + for (let i = 0; i < a_.length && i < b.length; ++i) { + if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers + if (!isNaN(a_[i]) && isNaN(b_[i])) return -1; + if (isNaN(a_[i]) && isNaN(b_[i])) { + let ret = a_[i].localeCompare(b_[i]); // Compare strings + if (ret !== 0) return ret; + } + if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers + if (a_[i] - b_[i] !== 0) return a_[i] - b_[i]; + } + } + + return 0; + }, + }; export default SeqUtils; diff --git a/test/index.js b/test/index.js index 4e0c6d43..dba360ca 100644 --- a/test/index.js +++ b/test/index.js @@ -20,6 +20,7 @@ import "./tests/operations/FlowControl.js"; import "./tests/operations/Image.js"; import "./tests/operations/MorseCode.js"; import "./tests/operations/StrUtils.js"; +import "./tests/operations/SeqUtils.js"; let allTestsPassing = true; const testStatusCounts = { diff --git a/test/tests/operations/SeqUtils.js b/test/tests/operations/SeqUtils.js new file mode 100644 index 00000000..7fc2c066 --- /dev/null +++ b/test/tests/operations/SeqUtils.js @@ -0,0 +1,33 @@ +/** + * SeqUtils tests. + * + * @author Chris van Marle + * @copyright Copyright 2017 + * @license Apache-2.0 + */ +import TestRegister from "../../TestRegister.js"; + +TestRegister.addTests([ + { + name: "SeqUtils - Numeric sort photos", + input: "Photo-1.jpg\nPhoto-4.jpg\nPhoto-2.jpg\nPhoto-3.jpg\n", + expectedOutput: "Photo-1.jpg\nPhoto-2.jpg\nPhoto-3.jpg\nPhoto-4.jpg\n", + recipeConfig: [ + { + "op": "Sort", + "args": ["Line feed", false, "Numeric"] + } + ], + }, + { + name: "SeqUtils - Numeric sort CVE IDs", + input: "CVE-2017-1234,CVE-2017-9999,CVE-2017-10000,CVE-2017-10001,CVE-2017-12345,CVE-2016-1234,CVE-2016-4321,CVE-2016-10000,CVE-2016-9999,CVE-2016-10001", + expectedOutput: "CVE-2017-12345,CVE-2017-10001,CVE-2017-10000,CVE-2017-9999,CVE-2017-1234,CVE-2016-10001,CVE-2016-10000,CVE-2016-9999,CVE-2016-4321,CVE-2016-1234", + recipeConfig: [ + { + "op": "Sort", + "args": ["Comma", true, "Numeric"] + } + ], + }, +]);