按日期字段对对象数组进行排序

66

给定以下对象数组,我需要按日期字段升序排序它们。

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

在上面的示例中,最终结果将是John Smith、Sam Snead和Joe Blow。

我正在尝试使用lodash的_.sortBy(),但无论如何我都无法进行任何排序:

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

我需要改变什么才能正确地对数组进行排序?我也有Moment.js,所以如果需要的话可以使用它来格式化日期字符串。我尝试使用.unix()转换日期属性,但没有任何效果。

谢谢。


那些是日期对象还是日期字符串? - Andreas Louv
标准的JavaScript日期字符串。如我所说,如果需要,我可以先使用Moment将它们转换为另一种格式,但是转换为Unix似乎不起作用,而这似乎是最容易排序的格式。 - wonder95
这些值是日期还是字符串? - Dekel
_.sortBy 似乎不会原地排序(不像 Array#sort 方法) - Jaromanda X
3
_.sortBy(myArray, ['date']) 应该可以实现排序。对于日期格式为 '2018-08-28T17:38:00' 的情况,它可以正常工作。 - Chaki_Black
可能是Lo-Dash sortBy array of dates in string format的重复问题。 - KyleMit
8个回答

108

您并不真的需要lodash。您可以使用JavaScript的Array.prototype.sort方法。

在比较之前,您需要从日期字符串创建Date对象。

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


2
它有极佳的浏览器支持。自 ECMAScript 3 规范制定以来,它就一直存在,这意味着它适用于所有浏览器。(甚至包括 IE7) - Marcelo Lazaroni
2
由于 OP 已经使用了 moment.js,因此应该使用它来解析日期,而不是内置的 Date。 - RobG
11
JavaScript的sort方法不是稳定排序,而lodash的sortBy和orderBy是稳定排序。我遇到过这样的问题,而lodash解决了它。sortBy方法执行的是稳定排序,即保留相等元素的原始排序顺序。 - WooodHead
另外要注意,Safari 对排序的处理方式不同。如果你已经使用了 lodash 或其他库,最好继续使用它们。 - Chopnut

26

使用标准JavaScript,将两个值转换为日期对象并比较它们的值来解决问题。

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

一个完整的代码片段:

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


23
您的日期值是字符串,因此您需要使用new Date()构造函数将它们更改为JavaScript date对象。这样,您就可以对它们进行排序(使用_.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>


16
如果您想使用lodash对对象数组中的日期进行升序或降序排序,应该使用_.orderBy而不是_.sortByhttps://lodash.com/docs/4.17.15#orderBy,该方法允许通过'asc'或'desc'指定排序顺序。例如:
const sortedArray = _(myArray.orderBy([
      function(object) {
        return new Date(object.date);
      }],["desc"])

9

使用Lodash更清晰的方式 orderBy

import _ from 'lodash'

const sortedArray = _.orderBy(myArray, [(obj) => new Date(obj.date)], ['asc'])

你在这里传递数组了吗? - Balaji
1
@ßãlãjî - 第一个参数是数组,即 _.orderBy(YOUR_ARRAY, ['asc'])。此外,asc 也可以是 desc,用于降序排序而不是升序...在这里了解更多信息。 - marsnebulasoup

7

只需编写_.sortBy({yourCollection}, {字段名});

lodash会自动识别这是一个日期,并且像魔术一样工作!

太棒了!


Lodash 真的会自动检测吗?即使提供的日期是 ISO 字符串? - Marek
1
@Marek,是的,lodash会自动检测字符串是否为ISO日期字符串,因此它会将其作为日期进行排序 :) - Roman Šimík
是的,如果日期采用ISO_8601格式。根据维基百科标准的一般原则:“日期和时间值按照从最大到最小的时间单位顺序排列:年、月(或周)、日、小时、分钟、秒和秒的分数。表示的字典顺序与时间顺序相对应,除了涉及负年份或时间偏移的日期表示。这使得日期可以自然地按照文件系统等进行排序。” - Adam M.

3

受他人答案的启发,同时注意到您使用了 moment.jslodash,您可以使用 lodash 的 _.orderBy 方法将二者结合起来:

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'])


1
这对我很有效。
myArray = _.orderBy(myArray, [item => item.lastModified], ['desc']);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接