From 0cbb17f7ce1ee99e3007852690debff356392218 Mon Sep 17 00:00:00 2001 From: Chris van Marle Date: Thu, 11 Oct 2018 13:21:13 +0200 Subject: [PATCH 1/4] Support hexadecimal and other bases in numeric sorting --- src/core/operations/Sort.mjs | 46 +++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/core/operations/Sort.mjs b/src/core/operations/Sort.mjs index 400d2cca18..dfb07c86fe 100644 --- a/src/core/operations/Sort.mjs +++ b/src/core/operations/Sort.mjs @@ -38,7 +38,7 @@ class Sort extends Operation { { "name": "Order", "type": "option", - "value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"] + "value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)"] } ]; } @@ -62,6 +62,8 @@ class Sort extends Operation { sorted = sorted.sort(Sort._ipSort); } else if (order === "Numeric") { sorted = sorted.sort(Sort._numericSort); + } else if (order === "Numeric (hexadecimal)") { + sorted = sorted.sort(Sort._hexadecimalSort); } if (sortReverse) sorted.reverse(); @@ -131,6 +133,48 @@ class Sort extends Operation { return a.localeCompare(b); } + /** + * Comparison operation for sorting of hexadecimal values. + * + * @author Chris van Marle + * @private + * @param {string} a + * @param {string} b + * @returns {number} + */ + static _hexadecimalSort(a, b) { + const a_ = a.split(/([^\da-f]+)/i), + b_ = b.split(/([^\da-f]+)/i); + + for (let i = 0; i < a_.length; ++i) { + let t = parseInt(a_[i], 16); + if (!isNaN(t)) { + a_[i] = t; + } + } + + for (let i = 0; i < b_.length; ++i) { + let t = parseInt(b_[i], 16); + if (!isNaN(t)) { + b_[i] = t; + } + } + + 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])) { + const 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 a.localeCompare(b); + } + } export default Sort; From 3b3c27072ff6780d2384a455652edd4db5dbee61 Mon Sep 17 00:00:00 2001 From: Chris van Marle Date: Thu, 11 Oct 2018 15:50:58 +0200 Subject: [PATCH 2/4] Fix lint errors --- src/core/operations/Sort.mjs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/operations/Sort.mjs b/src/core/operations/Sort.mjs index dfb07c86fe..20f797f810 100644 --- a/src/core/operations/Sort.mjs +++ b/src/core/operations/Sort.mjs @@ -146,19 +146,19 @@ class Sort extends Operation { const a_ = a.split(/([^\da-f]+)/i), b_ = b.split(/([^\da-f]+)/i); - for (let i = 0; i < a_.length; ++i) { - let t = parseInt(a_[i], 16); - if (!isNaN(t)) { - a_[i] = t; - } - } - - for (let i = 0; i < b_.length; ++i) { - let t = parseInt(b_[i], 16); - if (!isNaN(t)) { - b_[i] = t; - } - } + for (let i = 0; i < a_.length; ++i) { + const t = parseInt(a_[i], 16); + if (!isNaN(t)) { + a_[i] = t; + } + } + + for (let i = 0; i < b_.length; ++i) { + const t = parseInt(b_[i], 16); + if (!isNaN(t)) { + b_[i] = t; + } + } for (let i = 0; i < a_.length && i < b.length; ++i) { if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers From ba24e12454fcf19f9a319d7541793d4e1437faa4 Mon Sep 17 00:00:00 2001 From: Chris van Marle Date: Fri, 12 Oct 2018 15:39:06 +0200 Subject: [PATCH 3/4] Update hexadecimal sort after review - Use Array.map instead of for-loop - Add test case --- src/core/operations/Sort.mjs | 22 +++++++++------------- test/tests/operations/SeqUtils.mjs | 11 +++++++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/core/operations/Sort.mjs b/src/core/operations/Sort.mjs index 20f797f810..7e024d455c 100644 --- a/src/core/operations/Sort.mjs +++ b/src/core/operations/Sort.mjs @@ -143,22 +143,18 @@ class Sort extends Operation { * @returns {number} */ static _hexadecimalSort(a, b) { - const a_ = a.split(/([^\da-f]+)/i), + let a_ = a.split(/([^\da-f]+)/i), b_ = b.split(/([^\da-f]+)/i); - for (let i = 0; i < a_.length; ++i) { - const t = parseInt(a_[i], 16); - if (!isNaN(t)) { - a_[i] = t; - } - } + a_ = a_.map(v => { + const t = parseInt(v, 16); + return isNaN(t) ? v : t; + }); - for (let i = 0; i < b_.length; ++i) { - const t = parseInt(b_[i], 16); - if (!isNaN(t)) { - b_[i] = t; - } - } + b_ = b_.map(v => { + const t = parseInt(v, 16); + return isNaN(t) ? v : t; + }); for (let i = 0; i < a_.length && i < b.length; ++i) { if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers diff --git a/test/tests/operations/SeqUtils.mjs b/test/tests/operations/SeqUtils.mjs index 88acde8fa7..4516298a9d 100644 --- a/test/tests/operations/SeqUtils.mjs +++ b/test/tests/operations/SeqUtils.mjs @@ -30,4 +30,15 @@ TestRegister.addTests([ } ], }, + { + name: "SeqUtils - Hexadecimal sort", + input: "06,08,0a,0d,0f,1,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,2,3,4,5,7,9,b,c,e", + expectedOutput: "1,2,3,4,5,06,7,08,9,0a,b,c,0d,e,0f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f", + recipeConfig: [ + { + "op": "Sort", + "args": ["Comma", false, "Numeric (hexadecimal)"] + } + ], + }, ]); From 2d471f551f5de9ed545b591cb87c81937028eccf Mon Sep 17 00:00:00 2001 From: n1474335 Date: Wed, 7 Nov 2018 15:20:09 +0000 Subject: [PATCH 4/4] Lint --- test/tests/operations/RemoveDiacritics.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/tests/operations/RemoveDiacritics.mjs b/test/tests/operations/RemoveDiacritics.mjs index 52bf188fe0..5cc16da389 100644 --- a/test/tests/operations/RemoveDiacritics.mjs +++ b/test/tests/operations/RemoveDiacritics.mjs @@ -1,4 +1,3 @@ - /** * Remove Diacritics tests. *