Reputation: 6903
I would like to have a function to sort an array of objects by getting a string as input that include the name of the property and sort direction. I need something like this :
var myArray = [{name:"A", age: 30}, {name:"B", age:20}, {name:"C", age:20}];
var strSort = "age asc, name desc";
var sortedArray = customSortFuntion(myArray,strSort);
//sortedArray == [{name:"C", age:20}, {name:"B", age:20},{name:"A", age: 30}]
function customSortFuntion(myArray,strSort)
{
//return sorted by age asc and sorted by name desc etc..??
}
Upvotes: 6
Views: 265
Reputation: 30993
Here is my solution it's a custom sort function that takes the rules array, split it and check the properties values.
It takes the properties values on dynamically names using the bracket notation: foo['bar']
Code (tried a very little bit):
function customSortFuntion(myArray, strSort) {
var sortable = myArray;
var sortRules = strSort.split(',')
return sortable.sort(function (a, b) {
for (var s = 0; s < sortRules.length; s++) {
if (sortRules[s].split(' ')[1] == "asc") {
if (a[sortRules[s].split(' ')[0]] < b[sortRules[s].split(' ')[0]]) {
return 1
}
} else {
if (a[sortRules[s].split(' ')[0]] > b[sortRules[s].split(' ')[0]]) {
return 1
}
}
}
})
}
Demo: http://jsfiddle.net/IrvinDominin/8Z9xc/
You can use a regular expression to split with the presence of more spaces.
Code:
function customSortFuntion(myArray, strSort) {
var sortable = myArray;
var sortRules = strSort.split(',')
return sortable.sort(function (a, b) {
for (var s = 0; s < sortRules.length; s++) {
var sortRule=sortRules[s].split(/ +/)
if (sortRule[1] == "asc") {
if (a[sortRule[0]] < b[sortRule[0]]) {
return 1
}
} else {
if (a[sortRule[0]] > b[sortRule[0]]) {
return 1
}
}
}
})
}
Demo: http://jsfiddle.net/IrvinDominin/8Z9xc/1/
Upvotes: 1
Reputation: 272086
It would be easier if you transform this:
"age asc, name desc"
Into one of these:
[["age", "asc"], ["name", "desc"]]
[{ key: "age", dir: "asc" }, { key: "name", dir: "desc"}]
Here is a utility function which does just that:
function transformSortString(sortString) {
var sortParams = [],
temp = sortString.match(/[^ ,]+/g),
i;
for (i = 0; i < temp.length; i += 2) {
sortParams.push({
key: temp[i],
dir: temp[i + 1]
});
}
return sortParams;
}
And here is the multi-sort function to use with Array.sort. Very simple; compare a with b column by column, return -1 or +1 if the values differ:
function customSortFuntion(array, sortParams) {
array.sort(function (a, b) {
var i;
for (i = 0; i < sortParams.length; i++) {
if (a[sortParams[i].key] !== b[sortParams[i].key]) {
if (a[sortParams[i].key] < b[sortParams[i].key]) {
return sortParams[i].dir === "asc" ? -1 : 1;
}
if (a[sortParams[i].key] > b[sortParams[i].key]) {
return sortParams[i].dir === "asc" ? 1 : -1;
}
}
}
return 0;
});
}
Here is how you use it:
var myArray = [
{ name: "A", age: 10 },
{ name: "B", age: 10 },
{ name: "C", age: 10 },
];
customSortFuntion(myArray, transformSortString("age asc, name desc"));
And here is a demo:
Upvotes: 1
Reputation: 10070
This solution requires Array.prototype.map
("shim"-able) to present:
function customSortFunction(myArray,strSort){
var sorts=strSort.split(",").map(function(v,i){
var o=v.match(/\s(asc|desc)$/i);
if(o){
return {"prop":v.replace(/\s(asc|desc)$/i,"").replace(/^\s+|\s+$/,""),"order":o[1].toLowerCase()};
}else{
return {"prop":v,"order":"asc"};
}
});
myArray.sort(function(a,b){
var av,bv;
for(var i=0;i<sorts.length;i++){
av=a[sorts[i]["prop"]] || 0;
bv=b[sorts[i]["prop"]] || 0;
if(sorts[i]["order"]=="asc"){
if(av>bv){
return 1;
}else if(bv>av){
return -1;
}
}else{
if(av>bv){
return -1;
}else if(bv>av){
return 1;
}
}
}
return 0;
});
return myArray;
}
Given this array:
[
{name:"Z", age: 6},
{name:"Z", age: 19},
{name:"A", age: 30},
{name:"B", age: 20},
{name:"C", age: 20},
{name:"A", age: 31}
]
and sort order name asc, age desc
,
gives this output:
[ { name: 'A', age: 31 },
{ name: 'A', age: 30 },
{ name: 'B', age: 20 },
{ name: 'C', age: 20 },
{ name: 'Z', age: 19 },
{ name: 'Z', age: 6 } ]
Upvotes: 2
Reputation: 61
var myArray = [{name:"A", age: 30}, {name:"B", age:20}];
var strSort = "name asc, age asc";
var sortedArray = customSortFuntion(myArray,strSort);
function customSortFuntion(myArray,strSort)
{
var myarr = strSort.split(",");
// create a loop with 'myarr length'
var mysortarr=myarr[1].split(" ");
// mymysortarr 1 gives name and 2 gives asc or desc
if(mysortarr[2]=='desc')var entry= arr.sort(function(a,b) {
return b[0] > a[0];
});
if(mysortarr[2]=='asc')var entry = arr.sort(function(a,b) {
return a[1] > b[1];
});
alert(JSON.stringify(entry));
// end loop
}
Upvotes: 0
Reputation: 112
var myarray = [{name:'a',age : 30},{name:'b',age:20}];
var mysort = function(array,string){
for(var i=0; i<array.length; i++){
for(var key in array[i]){
if(array[i][key] == string){
console.log(array[i])
}
}
}
}
var b = mysort(myarray,'a');
//result {name = 'a', age = 30}
Use this code, it may be helpful.
Upvotes: 0
Reputation: 1013
Here is the logic:
function myFunction()
{
var arr = [[13, 'AAA'],[48, 'BBB'],[28, 'CCC'],[38, 'DDD']];
// First column * desc
arr = arr.sort(function(a,b) {
return b[0] > a[0];
});
// second column *ascc
arr = arr.sort(function(a,b) {
return a[1] > b[1];
});
}
Upvotes: 0