6

Well, I have an array objects with random values, Ex.

var arr = [
    { id:1001, date:"20-02-2014", Name: 'demo1' },
    { id:1004, date:"13-02-2014", Name: 'demo0' },
    { id:1000, date:"10-02-2014", Name: 'demo14' },
    { id:1004, date:"16-02-2014", Name: 'demo10' },
    { id:1006, date:"22-02-2014", Name: 'demo111' },
    { id:1003, date:"28-02-2014", Name: 'demo16' },
    { id:1000, date:"28-01-2014", Name: 'demo12' },
    { id:1004, date:"28-01-2014", Name: 'demo01' },
    { id:1000, date:"08-01-2014", Name: 'demo41' },
    { id:1006, date:"08-01-2014", Name: 'demo91' }
]

I wanted to sort this array firstly by key id & then by key date as,

Output:

sorted_arr = [
 {"id":1000,"date":"08-01-2014","Name":"demo41"}, //group1
 {"id":1000,"date":"28-01-2014","Name":"demo12"}, //group1
 {"id":1000,"date":"10-02-2014","Name":"demo14"}, //group1 
 {"id":1001,"date":"20-02-2014","Name":"demo1"},  //group2
 {"id":1003,"date":"28-02-2014","Name":"demo16"}, //group3
 {"id":1004,"date":"28-01-2014","Name":"demo01"}, //group4
 {"id":1004,"date":"13-02-2014","Name":"demo0"},  //group4
 {"id":1004,"date":"16-02-2014","Name":"demo10"}, //group4
 {"id":1006,"date":"08-01-2014","Name":"demo91"}  //group5
 {"id":1006,"date":"22-02-2014","Name":"demo111"} //group5
]

I tried few generic code to sort,

    // generic comparison function
    cmp = function(x, y){
      return x > y ? 1 : x < y ? -1 : 0; 
    };


    arr.sort(function(a, b){
       return cmp( 
          [cmp(a.id, b.id), cmp(a.date, b.date)], 
          [cmp(b.id, a.id), cmp(b.date, a.date)]
       );
    });

I referred few examples SO Example but not getting expected output. Please suggest me best way to get this.

6
  • 2
    So what sort functions have you tried? It should do something like compare id and if they're different, return 1, 0 or -1 according to some rule. If they're the same, return 1, 0 or -1 depending on the value of date and the required sort order. Note that you'll likely have to convert the date string to a date object, or re–order the parts and compare as strings. Commented Feb 24, 2014 at 6:41
  • @RobG: Please check updated info. & Could please explain me this through few sample of code. that could really help me out to understand. Commented Feb 24, 2014 at 6:46
  • possible duplicate of Sorting objects in an array by a field value in JavaScript Commented Feb 24, 2014 at 6:51
  • @Xotic750: Somehow its the same thing with different expected values. Its not giving me expected output. Commented Feb 24, 2014 at 6:54
  • 1
    Please read the MDN reference for Array.sort Your sort is incorrect and you need to understand how to use it. But yes, they are all the same thing, including what you are attempting. Commented Feb 24, 2014 at 6:56

5 Answers 5

8

No need to create Date objects, just reorder the date string into a sortable string, example

This example assumes that your dates are in the same format DD-MM-YYYY and creates YYYYMMDD for the date sort.

Javascript

var arr = [
    { id:1001, date:"20-02-2014", Name: 'demo1' },
    { id:1004, date:"13-02-2014", Name: 'demo0' },
    { id:1000, date:"10-02-2014", Name: 'demo14' },
    { id:1004, date:"16-02-2014", Name: 'demo10' },
    { id:1006, date:"22-02-2014", Name: 'demo111' },
    { id:1003, date:"28-02-2014", Name: 'demo16' },
    { id:1000, date:"28-01-2014", Name: 'demo12' },
    { id:1004, date:"28-01-2014", Name: 'demo01' },
    { id:1000, date:"08-01-2014", Name: 'demo41' },
    { id:1006, date:"08-01-2014", Name: 'demo91' }
];

var sorted = arr.sort(function (a, b) {
    return a.id - b.id || a.date.split('-').reverse().join('') - b.date.split('-').reverse().join('');
});

sorted.forEach(function (element) {
    console.log(JSON.stringify(element));
});

Output

{"id":1000,"date":"08-01-2014","Name":"demo41"}
{"id":1000,"date":"28-01-2014","Name":"demo12"}
{"id":1000,"date":"10-02-2014","Name":"demo14"}
{"id":1001,"date":"20-02-2014","Name":"demo1"} 
{"id":1003,"date":"28-02-2014","Name":"demo16"} 
{"id":1004,"date":"28-01-2014","Name":"demo01"} 
{"id":1004,"date":"13-02-2014","Name":"demo0"}
{"id":1004,"date":"16-02-2014","Name":"demo10"}
{"id":1006,"date":"08-01-2014","Name":"demo91"} 
{"id":1006,"date":"22-02-2014","Name":"demo111"} 

On jsFiddle

If there is any concern over mixing date formats, as discussed with @xdazz, then you can improve on this by checking the padding yourself. The following creates the format 'YYYYYYMMDD' when sorting by the date. The extra year padding is not necessary in this example as I am taking the numeric difference of the values, but if you choose to compare the strings then it is important.

function pad(s, n) {
    var v = '',
        i;

    for(i = 0; i < n - s.length; i += 1) {
        v += '0';
    }

    return v + s;
}

var sorted = arr.sort(function (a, b) {
    var idDiff = a.id - b.id;

    if (idDiff) {
        return idDiff;
    }

    var ordA = a.date.split('-').reverse(),
        ordB = b.date.split('-').reverse();

    ordA[0] = pad(ordA[0], 6);
    ordA[1] = pad(ordA[1], 2);
    ordA[2] = pad(ordA[2], 2);
    ordA = ordA.join('');
    ordB[0] = pad(ordB[0], 6);
    ordB[1] = pad(ordB[1], 2);
    ordB[2] = pad(ordB[2], 2);
    ordB = ordB.join('');
    return ordA - ordB;
});

On jsFiddle

If you really want to use Date objects the I would suggest the following.

var sorted = arr.sort(function (a, b) {
    var idDiff = a.id - b.id;

    if (idDiff) {
        return idDiff;
    }

    var ordA = a.date.split('-').reverse(),
        ordB = b.date.split('-').reverse();

    ordA[1] -= 1;
    ordB[1] -= 1;

    return new Date(Date.UTC.apply(undefined, ordA)).valueOf() -  new Date(Date.UTC.apply(undefined, ordB)).valueOf();
});

sorted.forEach(function (element) {
    console.log(JSON.stringify(element));
});

On jsFiddle

Note: These examples do not handle dates with negative years, again you would need to make further modifications.

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

2 Comments

How it will work when Name is same for some records and I want to sort firstly by key name& then by key date ?
This answer does not address that sort requirement as it is not what the OP asked.
5

First compare with id, then compare with date if id equal. But because your date is in invalid date format, extra work has to be done for letting it be recognized by Date.

sorted_arr = arr.sort(function(a, b) {
   return a.id - b.id || new Date(a.date.split('-').reverse().join('-')) - new Date(b.date.split('-').reverse().join('-'));
});

Edit: If you are guaranteed to have zeros in front of the 1-digit months and dates, then you could even not to parse to date:

sorted_arr = arr.sort(function(a, b) {
   return a.id - b.id || a.date.split('-').reverse().join('') - b.date.split('-').reverse().join('');
});

14 Comments

He should be able to sort the date strings without the need to create a Date object, as they can easily be made a sortable format.
+1. Indeed if one would use sortable date-time format like ISO8601 (YYYY-MM-DD) code would be simple.
@Xotic750 - DD-MM-YYYY is not sortable as text.
Master you deserve it +1
@Xotic750 OK, updated the answer if there are no mixing of zero padded dates and non-zero padded dates.
|
1

It's better to have a date operate lib momentjs to help. You could check the code on jsBin

function compare(a, b){
   var idDiff = a.id - b.id;
   var adate = moment(a.date, "DD-MM-YYYY");
   var bdate = moment(b.date, "DD-MM-YYYY");
   var dateDiff = adate.diff(bdate);
   return idDiff || dateDiff;
}

var sortedArr = arr.sort(compare);
console.log(sortedArr);

Comments

1

You can sort array by two properties with Alasql library:

var res = alasql('SELECT *, mid(date,7,4)+mid(date,4,2)+mid(date,1,2) AS ndate \
    FROM ? ORDER BY id, ndate',[arr]);

Try this example at jsFiddle.

Here "mid(date,7,4)+mid(date,4,2)+mid(date,1,2)" was used to convert date from '28-11-2014' to the sort key like '20141128'.

Comments

0

Came up with this using underscore.js & it's chain and sortBy:

var sorted_array = _(arr).chain().sortBy(function(o) {
    return o.date.split('-').reverse().join(); 
}).sortBy(function(o) {
    return o.id;
}).value();

Sorting on the date first, and then id will give you the list sorted as expected.

jsfiddle

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.