6

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..??
}
3
  • 1
    Douglas Crockford covers sorting in quite a bit of depth. This question should get ya started stackoverflow.com/questions/19437776/… Commented Jan 22, 2014 at 7:25
  • How do you mind will work? With strSort as your example what will be the result? Can you expand a bit? Commented Jan 22, 2014 at 7:37
  • I just want customSortFuntion to sort myArray. I think this syntax is very handy for developers to use. You can see the sorted result in my edited post. Commented Jan 22, 2014 at 7:47

6 Answers 6

2

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 } ]
Sign up to request clarification or add additional context in comments.

2 Comments

Great. Your solution is perfect. Thanks.
@Alborz Glad to be of help :)
1

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

Comments

1

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/

1 Comment

Thanks. It works. But it fails if the strSort has more space between propery and direction. Can it be resolved?
0

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

1 Comment

This is not what i want. I would like pass the strSort .
0
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.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.