66

Given the following array of objects, I need to ascending sort them by the date field.

var myArray = [
  {
    name: "Joe Blow",
    date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "Sam Snead",
    date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "John Smith",
    date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"  
  }
];

In the above example, the final result would be John Smith, Sam Snead, and Joe Blow.

I am trying to use lodash's _.sortBy(), but I can't get any sorting to take place no matter how I try to use it:

_.sortBy(myArray, function(dateObj) {
  return dateObj.date;
});

or

_.sortBy(myArray, 'date');

What do I need to change to get my array sorted properly? I also have Moment.js, so I can use it to format the date string if needed. I tried converting the date property using .unix(), but that didn't make a difference.

Thanks.

Dave Mackey
  • 4,306
  • 21
  • 78
  • 136
wonder95
  • 3,825
  • 8
  • 45
  • 74

8 Answers8

108

You don't really need lodash. You can use JavaScript's Array.prototype.sort method.

You'll need to create Date objects from your date strings before you can compare them.

var myArray = [{
  name: "Joe Blow",
  date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
}, {
  name: "Sam Snead",
  date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
}, {
  name: "John Smith",
  date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"
}];

myArray.sort(function compare(a, b) {
  var dateA = new Date(a.date);
  var dateB = new Date(b.date);
  return dateA - dateB;
});

console.log(myArray);
Punit
  • 1,917
  • 1
  • 11
  • 12
  • 2
    And it has great Browser support. It's been in the spec since ECMAScript 3, which means it works in all browsers. (even IE7) – Marcelo Lazaroni Dec 05 '16 at 01:27
  • 2
    Since the OP has moment.js, it should be used to parse the dates, not the built–in Date. – RobG Dec 05 '16 at 02:08
  • 11
    JavaScript sort is not stable sort, lodash sortBy and orderBy are stable. I have encountered a problem about this, and lodash solved it. `This method performs a stable sort, that is, it preserves the original sort order of equal elements.` https://lodash.com/docs/4.17.10#sortBy – WooodHead Sep 10 '18 at 03:05
  • Also to add safari does its sorting differently. Found it the hard way, if you already have lodash or other libraries , best to use them. – Chopnut May 24 '19 at 08:15
26

Here's a solution using standard Javascript by converting both values to date object and comparing their value.

myArray.sort((d1, d2) => new Date(d1.date).getTime() - new Date(d2.date).getTime());

A complete snippet:

var myArray = [
  {
    name: "Joe Blow",
    date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "Sam Snead",
    date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "John Smith",
    date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"  
  }
];

myArray.sort((d1, d2) => new Date(d1.date).getTime() - new Date(d2.date).getTime());

console.log(myArray);
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
23

Your date values are strings, so you need to use the new Date() constructor to change them to javascript date objects. This way you can sort them (using _.sortBy).

var myArray = [
  {
    name: "Joe Blow",
    date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "Sam Snead",
    date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "John Smith",
    date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"  
  }
];

myArray = _.sortBy(myArray, function(dateObj) {
  return new Date(dateObj.date);
});

console.log(myArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
Dekel
  • 60,707
  • 10
  • 101
  • 129
16

If you are trying to use lodash to sort dates in ascending or descending order for your array of objects, you should use _.orderBy instead of _.sortBy

https://lodash.com/docs/4.17.15#orderBy, this method allows specifying sort orders either by 'asc' or 'desc'

An example would be:

const sortedArray = _(myArray.orderBy([
      function(object) {
        return new Date(object.date);
      }],["desc"])
Darsshan
  • 896
  • 1
  • 11
  • 22
9

A cleaner way using Lodash orderBy:

import _ from 'lodash'

const sortedArray = _.orderBy(myArray, [(obj) => new Date(obj.date)], ['asc'])
David Ferreira
  • 1,233
  • 17
  • 24
  • where you pass array here? – Balaji May 26 '21 at 21:35
  • 1
    @ßãlãjî - First param is the array, i.e. `_.orderBy(YOUR_ARRAY, ['asc'])`. Also, `asc` can be `desc` also for descending sorting instead of ascending...see more [here](https://lodash.com/docs/4.17.15#orderBy) – marsnebulasoup May 28 '21 at 17:58
7

just write _.sortBy({yourCollection}, {the field name});

lodash will automatically figure that this is a date and it'll work like a magic!

Awesome!

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
oded
  • 109
  • 1
  • 1
  • Will lodash really detect this automatically? Even if the provided date is a ISO string? – Marek Sep 27 '20 at 15:20
  • 1
    @Marek, yes lodash detects automatically that if string is ISO Date String, so it then sorts it as Date :) – Roman Šimík Jun 15 '21 at 15:13
  • Yes, if the date is in ISO_8601 format. From Wikipedia as a general principle of the standard: "Date and time values are ordered from the largest to smallest unit of time: year, month (or week), day, hour, minute, second, and fraction of second. The lexicographical order of the representation thus corresponds to chronological order, except for date representations involving negative years or time offset. This allows dates to be naturally sorted by, for example, file systems. – Adam M. Nov 10 '21 at 22:46
3

Inspired by others answers and noticing that you used moment.js and lodash, you can combine both with _.orderBy lodash method:

import moment from 'moment'
import * as _ from 'lodash'

let myArray = [
  {
    name: "Joe Blow",
    date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "Sam Snead",
    date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"
  },
  {
    name: "John Smith",
    date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"  
  }
];


myArray = _.orderBy(myArray, [(item) => {
            return moment(item.date).format('YYYY-MM-DD')
         }], ['desc'])
Juliette
  • 41
  • 2
1

this has worked for me

myArray = _.orderBy(myArray, [item => item.lastModified], ['desc']);
sean717
  • 11,759
  • 20
  • 66
  • 90