Browse Source

Support hexadecimal and other bases in numeric sorting

Chris van Marle 6 years ago
parent
commit
0cbb17f7ce
1 changed files with 45 additions and 1 deletions
  1. 45 1
      src/core/operations/Sort.mjs

+ 45 - 1
src/core/operations/Sort.mjs

@@ -38,7 +38,7 @@ class Sort extends Operation {
             {
             {
                 "name": "Order",
                 "name": "Order",
                 "type": "option",
                 "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);
             sorted = sorted.sort(Sort._ipSort);
         } else if (order === "Numeric") {
         } else if (order === "Numeric") {
             sorted = sorted.sort(Sort._numericSort);
             sorted = sorted.sort(Sort._numericSort);
+        } else if (order === "Numeric (hexadecimal)") {
+            sorted = sorted.sort(Sort._hexadecimalSort);
         }
         }
 
 
         if (sortReverse) sorted.reverse();
         if (sortReverse) sorted.reverse();
@@ -131,6 +133,48 @@ class Sort extends Operation {
         return a.localeCompare(b);
         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;
 export default Sort;