3

I have an array of objects similar in design as listed below. I would like to sort this array first by by the ClassName (alphabetically), then by the StartDate, but I want to preserve the initial sorting. I understand I can likely use sort() to accomplish this but I'm not sure how to preserve the initial sorting w/o breaking the original array into smaller groupings.

var objArray = [
    {
        ClassName: "Excel",
        Location: "Kansas City",
        StartDate: "2/1/2016",
        EndDate: "6/2/2016,"
    },
    {
        ClassName: "Outlook",
        Location: "Kansas City",
        StartDate: "1/1/2016",
        EndDate: "5/2/2016,"
    },
    {
        ClassName: "Excel",
        Location: "Kansas City",
        StartDate: "3/1/2016",
        EndDate: "7/2/2016,"
    }
];

Ideally based on the data above I'd end up with something like this:

var objArray = [
    {
        ClassName: "Excel",
        Location: "Kansas City",
        StartDate: "2/1/2016",
        EndDate: "6/2/2016,"
    },
    {
        ClassName: "Excel",
        Location: "Kansas City",
        StartDate: "3/1/2016",
        EndDate: "7/2/2016,"
    },
    {
        ClassName: "Outlook",
        Location: "Kansas City",
        StartDate: "1/1/2016",
        EndDate: "5/2/2016,"
    }
];

and again for clarity, if there were multiple classes the final sorting would end up looking something like this.

Excel (1/1/2016)
Excel (1/2/2016)
Excel (2/3/2016)
Outlook (1/3/2016)
Outlook (2/3/2016)
Word (1/1/2016)
Word (5/5/2016)
2
  • 2
    When you say "preserve the original sorting", you mean a stable sort? Commented Oct 12, 2016 at 14:06
  • @Emed Thanks for the link, this helped me find a working solution. I knew somewhere else there had to be a solution already I just couldn't find the right search terms. Commented Oct 12, 2016 at 14:40

3 Answers 3

2

The link @emed pointed to for possible duplicate, had an interesting solution.

My only issue with it would have been performance, as he's doing map's and reduce constantly inside the compare function.

So I've done a slightly modified version, and I've also kept the ability to do reverse sorting.

var objArray = [
    {
        ClassName: "Excel",
        Location: "Kansas City",
        StartDate: "2/1/2016",
        EndDate: "6/2/2016,"
    },
    {
        ClassName: "Outlook",
        Location: "Kansas City",
        StartDate: "1/1/2016",
        EndDate: "5/2/2016,"
    },
    {
        ClassName: "Excel",
        Location: "Kansas City",
        StartDate: "3/1/2016",
        EndDate: "7/2/2016,"
    }
];

objArray.sort(fieldSorter(['ClassName', 'StartDate']));
console.log(objArray);

function fieldSorter(fields) {
    var maps = [];
    fields.map(function (o) {
       var dir = +1;
       if (o[0] === '-') {
          dir = -1;
          o=o.substring(1);
       }
       maps.push({fn:o, dir:dir});
    });
    return function (a, b) {
       var ret = 0;
       maps.some(function (o) {
         if (a[o.fn] > b[o.fn]) ret = o.dir;
         else if (a[o.fn] < b[o.fn]) ret = -o.dir;
         else ret = 0;
         return ret !== 0;
       });
       return ret;
    };
}

Sign up to request clarification or add additional context in comments.

Comments

0

For future reference: this is the function I ended up using to solve the issue. Thank you all for your input:

function fieldSorter(fields) {
    return function (a, b) {
        return fields
            .map(function (o) {
                var dir = 1;
                if (o[0] === '-') {
                   dir = -1;
                   o=o.substring(1);
                }
                if (a[o] > b[o]) return dir;
                if (a[o] < b[o]) return -(dir);
                return 0;
            })
            .reduce(function firstNonZeroValue (p,n) {
                return p ? p : n;
            }, 0);
    };
}

Comments

0

array.sort() is working fine, where you face the issue.

console.log(JSON.stringify(objArray.sort()));

or looking for something like this

objArray.sort(function(a, b) {
    var classA = a.ClassName.toLowerCase(), classB = b.ClassName.toLowerCase();
    if(classA<classB){
        return -1;}
    if(classA>classB){
        return 1;}
    return 0;
});

objArray.sort(function(a, b) {

    var classA = a.ClassName.toLowerCase(), classB = b.ClassName.toLowerCase();
    if(classA===classB){
            var startA =new Date(a.StartDate), startB=new Date(b.StartDate);
            return startA-startB;
     }
    return 0;
});

1 Comment

But I don't think you can just say objArray.sort() without specifying how to sort.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.