I've used the typical INT array sort function found all over the internet for years, but I've also had a need to sort other items in an array, or even to just simple take an Array
of multiple types of items and get it in order for later readability. Thus leading me to the smartSort
method I list below. If I've anything else I can think to implement at the moment (will update later), it's that I currently don't have a parameter for sorting Objects by a specific property.
The method (what work it does)
At current, it will sort a variety of items in an array; Ascending or Descending. If there are more than one type of item, then the types are grouped together in a somewhat (at least to me) logical fashion: Ints, Strings, Arrays, Unspecified Objects, Element Objects, Date Objects, nulls & undefines. However, within each group, the items are still sorted based on given parameter.
The simplicity is in only needing to supply 1 to 2 parameters (based on implementation, pure method form needs supplied Array of course). The main parameter is simply a string being 'asc'
or 'desc'
.
Implementation
Comes in 2 flavors. One, requiring EcmaScript 5.1, simply adds it to Array.prototype
. Thus making it naturally easy to call, such as: myArray.smartSort('asc')
.
The other is a traditional method, of course. Old fashioned calling like: smartSort(myArray, 'asc')
.
Added Ease
Also implemented in both flavors is the ease of use on the String parameter. If no parameter is provided, than 'asc' is assumed.
Also implemented in flavor 2 is the ease of parameter order. It doesn't matter if you place the Array or the String first, as long as, at the least, the Array
exist.
More Perks
Of course, simple things like Ints and Strings are handled in proper manner, including real number sorting as opposed to traditional .sort
of JS. However, this will also sort Array
s and Objects based on items/properties, after sorting those accordingly. For example, if you have 3 arrays that all look like [ 'a', 'b' ]', but then
push` a different string on each one, they will be sorted based on the 3rd string. Same for objects and their properties. The one exception, Dates Objects, are sorted by their date given date.
Array.prototype.smartSort('asc|desc')
if (Object['defineProperty'] && !Array.prototype['smartSort']) {
var smartSortAsc = function(a, b) {
if (a == null || a == undefined) return 1;
if (b == null || b == undefined) return -1;
var c = typeof a, d = typeof b, e = c + d;
if (/^numbernumber$/ig.test(e)) return a - b;
if (/^stringstring$/ig.test(e)) return a > b;
if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1;
if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/^objectobject$/ig.test(e)) {
if (a instanceof Array) a.smartSort('a');
if (b instanceof Array) b.smartSort('a');
if (a instanceof Date && b instanceof Date) return a - b;
if (a instanceof Array && b instanceof Array) {
var f = Object.keys(a),
g = Object.keys(b),
h = f.concat(g).smartSort('a');
for (var x in h) {
var i = h[x];
if (a[i] != b[i]) {
var j = [ a[i], b[i] ].smartSort('a');
return a[i] == j[0] ? -1 : 1;
}
}
var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a');
return a[Object.keys(a)[0]] == k[0] ? -1 : 1;
}
if (a instanceof Element && b instanceof Element) {
if (a.tagName == b.tagName) {
var f = [ a.id, b.id ].smartSort('a');
return a.id == f[0] ? 1 : -1;
}
var f = [ a.tagName, b.tagName ].smartSort('a');
return a.tagName == f[0] ? 1 : -1;
}
if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1;
if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1;
var f = Object.keys(a),
g = Object.keys(b),
h = f.concat(g).smartSort('a');
for (var i = 0; i < 20; i++) {
var j = f[i], k = g[i];
if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {
if (a[j] instanceof Element && b[k] instanceof Element) {
if (a[j].tagName == b[k].tagName) {
var l = [ a[j].id, b[k].id ].smartSort('a');
return a[j].id == l[0] ? -1 : 1;
}
var l = [ a[j].tagName, b[k].tagName ].smartSort('a');
return a[j].tagName == l[0] ? -1 : 1;
}
if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1;
if (a[j] != b[k]) {
var m = [ a[j], b[k] ].smartSort('a');
return a[j] == m[0] ? -1 : 1;
}
}
if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;
if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1;
if (!a.hasOwnProperty(j)) return -1;
if (!b.hasOwnProperty(j)) return 1;
}
var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a');
return a[Object.keys(a)[0]] == m[0] ? 1 : -1;
}
var g = [a, b].sort();
return g[0] > g[1];
}
var smartSortDesc = function(a, b) {
if (a == null || a == undefined) return 1;
if (b == null || b == undefined) return -1;
var c = typeof a, d = typeof b, e = c + d;
if (/^numbernumber$/ig.test(e)) return b - a;
if (/^stringstring$/ig.test(e)) return b > a;
if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1;
if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/^objectobject$/ig.test(e)) { // both are OBJECT
if (a instanceof Array) a.smartSort('d');
if (b instanceof Array) b.smartSort('d');
if (a instanceof Date && b instanceof Date) return b - a;
if (a instanceof Array && b instanceof Array) { // both are ARRAY
var f = Object.keys(a),
g = Object.keys(b),
h = f.concat(g).smartSort('a');
for (var x in h) {
var i = h[x];
if (a[i] != b[i]) {
var j = [ a[i], b[i] ].smartSort('d');
return a[i] == j[0] ? -1 : 1;
}
}
var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d');
return a[Object.keys(a)[0]] == k[0] ? -1 : 1;
}
if (a instanceof Element && b instanceof Element) { // both are ELEMENT
if (a.tagName == b.tagName) {
var f = [ a.id, b.id ].smartSort('d');
return a.id == f[0] ? -1 : 1;
}
var f = [ a.tagName, b.tagName ].smartSort('d');
return a.tagName == f[0] ? -1 : 1;
}
if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1;
if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1;
var f = Object.keys(a),
g = Object.keys(b),
h = f.concat(g).smartSort('a');
for (var i = 0; i < 20; i++) {
var j = f[i], k = g[i];
if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {
if (a[j] instanceof Element && b[k] instanceof Element) {
if (a[j].tagName == b[k].tagName) {
var l = [ a[j].id, b[k].id ].smartSort('d');
return a[j].id == l[0] ? -1 : 1;
}
var l = [ a[j].tagName, b[k].tagName ].smartSort('d');
return a[j].tagName == l[0] ? -1 : 1;
}
if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1;
if (a[j] != b[k]) {
var m = [ a[j], b[k] ].smartSort('d');
return a[j] == m[0] ? -1 : 1;
}
}
if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;
if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1;
if (!a.hasOwnProperty(j)) return 1;
if (!b.hasOwnProperty(j)) return -1;
}
var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d');
return a[Object.keys(a)[0]] == m[0] ? -1 : 1;
}
var g = [a, b].sort();
return g[0] < g[1];
}
Object.defineProperty(Array.prototype, 'smartSort', {
value: function() {
if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0])))
return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc);
return this.sort();
}
});
}
smartSort(Array, 'asc|desc')
if (!window['smartSort']) {
window.smartSort = function() {
if (arguments) {
var a, b;
for (var x in arguments) arguments[x] instanceof Array && (a = arguments[x], void 0 == b && (b = "a")), "string" == typeof arguments[x] && (b = /^a([sc]{2})?$/i.test(arguments[x]) ? "a" : "d");
if (a instanceof Array) return a.sort(b == 'a' ? smartSort.asc : smartSort.desc);
}
return this.sort();
}
smartSort.asc = function(a, b) {
if (a == null || a == undefined) return 1;
if (b == null || b == undefined) return -1;
var c = typeof a, d = typeof b, e = c + d;
if (/^numbernumber$/ig.test(e)) return a - b;
if (/^stringstring$/ig.test(e)) return a > b;
if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1;
if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/^objectobject$/ig.test(e)) {
if (a instanceof Array) a.sort(smartSort.asc);
if (b instanceof Array) b.sort(smartSort.asc);
if (a instanceof Date && b instanceof Date) return a - b;
if (a instanceof Array && b instanceof Array) {
var f = Object.keys(a),
g = Object.keys(b),
h = smartSort(f.concat(g), 'a');
for (var x in h) {
var i = h[x];
if (a[i] != b[i]) {
var j = smartSort([ a[i], b[i] ], 'a');
return a[i] == j[0] ? -1 : 1;
}
}
var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a');
return a[Object.keys(a)[0]] == k[0] ? -1 : 1;
}
if (a instanceof Element && b instanceof Element) {
if (a.tagName == b.tagName) {
var f = smartSort([ a.id, b.id ], 'a');
return a.id == f[0] ? 1 : -1;
}
var f = smartSort([ a.tagName, b.tagName ], 'a');
return a.tagName == f[0] ? 1 : -1;
}
if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1;
if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1;
var f = Object.keys(a),
g = Object.keys(b),
h = smartSort(f.concat(g), 'a');
for (var i = 0; i < 20; i++) {
var j = f[i], k = g[i];
if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {
if (a[j] instanceof Element && b[k] instanceof Element) {
if (a[j].tagName == b[k].tagName) {
var l = smartSort([ a[j].id, b[k].id ], 'a');
return a[j].id == l[0] ? -1 : 1;
}
var l = smartSort([ a[j].tagName, b[k].tagName ], 'a');
return a[j].tagName == l[0] ? -1 : 1;
}
if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1;
if (a[j] != b[k]) {
var m = smartSort([ a[j], b[k] ], 'a');
return a[j] == m[0] ? -1 : 1;
}
}
if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;
if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1;
if (!a.hasOwnProperty(j)) return -1;
if (!b.hasOwnProperty(j)) return 1;
}
var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a');
return a[Object.keys(a)[0]] == m[0] ? 1 : -1;
}
var g = [a, b].sort();
return g[0] > g[1];
}
smartSort.desc = function(a, b) {
if (a == null || a == undefined) return 1;
if (b == null || b == undefined) return -1;
var c = typeof a, d = typeof b, e = c + d;
if (/^numbernumber$/ig.test(e)) return b - a;
if (/^stringstring$/ig.test(e)) return b > a;
if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1;
if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;
if (/^objectobject$/ig.test(e)) { // both are OBJECT
if (a instanceof Array) a.sort(smartSort.desc);
if (b instanceof Array) b.sort(smartSort.desc);
if (a instanceof Date && b instanceof Date) return b - a;
if (a instanceof Array && b instanceof Array) { // both are ARRAY
var f = Object.keys(a),
g = Object.keys(b),
h = smartSort(f.concat(g), 'a');
for (var x in h) {
var i = h[x];
if (a[i] != b[i]) {
var j = smartSort([ a[i], b[i] ], 'd');
return a[i] == j[0] ? -1 : 1;
}
}
var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd');
return a[Object.keys(a)[0]] == k[0] ? -1 : 1;
}
if (a instanceof Element && b instanceof Element) { // both are ELEMENT
if (a.tagName == b.tagName) {
var f = smartSort([ a.id, b.id ], 'd');
return a.id == f[0] ? -1 : 1;
}
var f = smartSort([ a.tagName, b.tagName ], 'd');
return a.tagName == f[0] ? -1 : 1;
}
if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1;
if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1;
var f = Object.keys(a),
g = Object.keys(b),
h = smartSort(f.concat(g), 'a');
for (var i = 0; i < 20; i++) {
var j = f[i], k = g[i];
if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {
if (a[j] instanceof Element && b[k] instanceof Element) {
if (a[j].tagName == b[k].tagName) {
var l = smartSort([ a[j].id, b[k].id ], 'd');
return a[j].id == l[0] ? -1 : 1;
}
var l = smartSort([ a[j].tagName, b[k].tagName ], 'd');
return a[j].tagName == l[0] ? -1 : 1;
}
if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1;
if (a[j] != b[k]) {
var m = smartSort([ a[j], b[k] ], 'd');
return a[j] == m[0] ? -1 : 1;
}
}
if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;
if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1;
if (!a.hasOwnProperty(j)) return 1;
if (!b.hasOwnProperty(j)) return -1;
}
var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd');
return a[Object.keys(a)[0]] == m[0] ? -1 : 1;
}
var g = [a, b].sort();
return g[0] < g[1];
}
}
Other than the obvious implementation of an alternate param for sorting by a specific Object Property, what could I improve to make it more flexible or even extend its functionality?