Alborz
Alborz

Reputation: 6903

Sorting an array of objects specifying sort criteria as a string

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

Answers (6)

Irvin Dominin
Irvin Dominin

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/

UPDATE

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

Salman Arshad
Salman Arshad

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:

Demo

Upvotes: 1

Passerby
Passerby

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;
}

Online demo

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

najeeb k rahman
najeeb k rahman

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

Sathish RG
Sathish RG

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

Bharathi D
Bharathi D

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

Related Questions