How to write a generic sorting function in the style orderBy thenBy that sort an array by a list of properties provided as an array.
Thanks for all great answers. For information, I discovered that a recursive approach is also an alternative solution
function sortByThenBy(items, keys) {
return items.sort(function(it1, it2){return compare(it1, it2, keys);});
}
function compare(it1, it2, keys, index) {
index = index || 0;
var currentKey = keys[index];
return it1[currentKey] < it2[currentKey] ? 1 : (it1[currentKey] > it2[currentKey] ? -1 : compare(it1, it2, keys, index + 1));
}
I think you can do as follows;
function sortBy(a,p){
return a.sort(function(a,b){
var sp = p.find(k => a[k] - b[k]); // find the property to compare;
return a[sp] - b[sp];
});
}
var items = [{ name: "AA", prop1 : 12, prop2: 13, prop3: 5, prop4: 26 },
{ name: "AA", prop1 : 12, prop2: 13, prop3: 6, prop4: 23 },
{ name: "AA", prop1 : 12, prop2: 14, prop3: 5, prop4: 23 },
{ name: "AA", prop1 : 11, prop2: 13, prop3: 5, prop4: 22 },
{ name: "AA", prop1 : 10, prop2: 13, prop3: 9, prop4: 21 }
];
console.log(sortBy(items,["prop1", "prop3", "prop4"]));
console.log(sortBy(items,["prop1", "prop3"]));
console.log(sortBy(items,["prop4", "prop3"]));
try this solution.I'm creating sequence with data used in comparision like data1|0000NumberData2|data3
. After that using native sort JS function to compare this sequence.
To avoid string comparision problem with numbers - zero padding used 000000345
So you can specify fields to use and fields sequence.
var items = [{ name: "AA", prop1 : 12, prop2: 13, prop3: 5, prop4: 22 },
{ name: "AA", prop1 : 2, prop2: 13, prop3: 6, prop4: 23 },
{ name: "AB", prop1 : 12, prop2: 14, prop3: 5, prop4: 23 },
{ name: "AA", prop1 : 11, prop2: 13, prop3: 5, prop4: 22 },
{ name: "AA", prop1 : 10, prop2: 13, prop3: 9, prop4: 21 }];
// sort by prop1 then by prop3 then by prop4:
var sortedItems = sortByThenBy(items, ["prop1", "prop3", "prop4"]);
console.log(sortedItems);
// sort by prop1 then by prop3:
var sortedItems = sortByThenBy(items, ["prop1", "prop3"]);
console.log(sortedItems);
function sortByThenBy(items, props) {
return items.sort(function(a, b) {
var a_path = $.map(props, function(item) {
var ret = a[item];
return isNumber(ret) ? pad(ret, 10) : ret;
}).join('|');
var b_path = $.map(props, function(item) {
var ret = b[item];
return isNumber(ret) ? pad(ret, 10) : ret;
}).join('|');
return a_path > b_path ? 1 : (a_path == b_path ? 0 : -1);
});
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function pad(n, width) {
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
Do it using Array#sort
and Array#reduce
methods.
function sortByThenBy(arr, props) {
// apply custom sort function on array
return arr.sort(function(a, b) {
// generate compare function return value by
// iterating over the properties array
return props.reduce(function(bool, k) {
// if previous compare result is `0` then compare
// with the next property value and return result
return bool || (a[k] - b[k]);
// set initial value as 0
}, 0);
})
}
var items = [{
name: "AA",
prop1: 12,
prop2: 13,
prop3: 5,
prop4: 22
}, {
name: "AA",
prop1: 12,
prop2: 13,
prop3: 6,
prop4: 23
}, {
name: "AA",
prop1: 12,
prop2: 14,
prop3: 5,
prop4: 23
}, {
name: "AA",
prop1: 11,
prop2: 13,
prop3: 5,
prop4: 22
}, {
name: "AA",
prop1: 10,
prop2: 13,
prop3: 9,
prop4: 21
}];
console.log(sortByThenBy(items, ["prop1", "prop3", "prop4"]));
console.log(sortByThenBy(items, ["prop1", "prop3"]));
console.log(sortByThenBy(items, ["prop2", "prop3"]));
function sortByThenBy(arr, props) {
return arr.sort(function(a, b) {
return props.reduce(function(bool, k) {
return bool || (a[k] - b[k]);
}, 0);
})
}
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
You could iterate the keys and use Array#some for getting the order value.
This proposal works with a short circuit, if a delta is truthy (!== 0
), then the iteration breaks and the delta is returned to the sort callback.
function sortByThenBy(array, keys) {
return array.sort(function (a, b) {
var r = 0;
keys.some(function (k) {
return r = a[k] - b[k];
});
return r;
});
}
var items = [{ name: "AA", prop1: 12, prop2: 13, prop3: 5, prop4: 22 }, { name: "AA", prop1: 12, prop2: 13, prop3: 6, prop4: 23 }, { name: "AA", prop1: 12, prop2: 14, prop3: 5, prop4: 23 }, { name: "AA", prop1: 11, prop2: 13, prop3: 5, prop4: 22 }, { name: "AA", prop1: 10, prop2: 13, prop3: 9, prop4: 21 }];
console.log(sortByThenBy(items, ["prop1", "prop3", "prop4"]));
console.log(sortByThenBy(items, ["prop1", "prop3"]));
console.log(sortByThenBy(items, ["prop3", "prop1", "prop4"]));
.as-console-wrapper { max-height: 100% !important; top: 0; }