按具有日期值的单个键对对象数组进行排序

IT技术 javascript arrays object
2021-01-24 14:05:42

我有一个包含多个键值对的对象数组,我需要根据“updated_at”对它们进行排序:

[
    {
        "updated_at" : "2012-01-01T06:25:24Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-09T11:25:13Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-05T04:13:24Z",
        "foo" : "bar"
    }
]

这样做的最有效方法是什么?

6个回答

您可以使用Array.sort.

下面是一个例子:

var arr = [{
    "updated_at": "2012-01-01T06:25:24Z",
    "foo": "bar"
  },
  {
    "updated_at": "2012-01-09T11:25:13Z",
    "foo": "bar"
  },
  {
    "updated_at": "2012-01-05T04:13:24Z",
    "foo": "bar"
  }
]

arr.sort(function(a, b) {
  var keyA = new Date(a.updated_at),
    keyB = new Date(b.updated_at);
  // Compare the 2 dates
  if (keyA < keyB) return -1;
  if (keyA > keyB) return 1;
  return 0;
});

console.log(arr);

不适用于 Chrome 移动版 >= 88.0.4324.152
2021-03-21 14:05:42
不需要转换为日期对象,因为 ISO 格式的字母顺序和时间顺序是相同的。所以你可以只按字符串排序。只要所有值都采用正确的 ISO 格式(包括采用 UTC)
2021-03-30 14:05:42
如果您想根据键中的数值进行排序,那么这个 ES6 one-liner 可能会有所帮助。yourArr.sort((a, b) => a.yourNumericOrderingKey > b.yourNumericOrderingKey). 在我的情况下,我必须根据order主数组对象内的键进行排序
2021-04-01 14:05:42
你不能使用keyA - keyB(或可能keyB - keyA)吗?日期对象有一个valueOf()方法。
2021-04-06 14:05:42

我已经在这里回答了一个非常相似的问题:Simple function to sort an array of objects

对于那个问题,我创建了这个小函数,它可以做你想做的事:

function sortByKey(array, key) {
    return array.sort(function(a, b) {
        var x = a[key]; var y = b[key];
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
}
不适用于 Chrome 移动版 >= 88.0.4324.152
2021-04-08 14:05:42

所述的Array.sort()方法进行排序的阵列的代替元素并返回数组。小心Array.sort()因为它不是Immutable对于不可变排序,请使用immutable-sort

此方法是使用当前updated_at的 ISO 格式对数组进行排序我们new Data(iso_string).getTime()用来将 ISO 时间转换为 Unix 时间戳。Unix 时间戳是一个我们可以做简单数学运算的数字。我们减去第一个和第二个时间戳,结果是;如果第一个时间戳大于第二个,则返回数字将为正。如果第二个数字大于第一个,则返回值将为负数。如果两者相同,则返回为零。这与内联函数所需的返回值完全一致。

对于ES6

arr.sort((a,b) => new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime());

对于ES5

arr.sort(function(a,b){ 
 return new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime();
});

如果您将您的updated_at时间戳更改为 unix 时间戳,您可以执行以下操作:

对于ES6

arr.sort((a,b) => a.updated_at - b.updated_at);

对于ES5

arr.sort(function(a,b){ 
 return a.updated_at - b.updated_at;
});

在撰写本文时,现代浏览器不支持 ES6。要在现代浏览器中使用 ES6,请使用babel将代码转换为 ES5。期待浏览器在不久的将来支持 ES6。

Array.sort()应该接收 3 种可能结果之一的返回值:

  • 一个正数(第一项 > 第二项)
  • 负数(第一项 < 第二项)
  • 0 如果两项相等

请注意,内联函数的返回值可以是任何正数或负数。Array.Sort() 不关心返回数字是什么。它只关心返回值是正数、负数还是零。

对于不可变排序:(以 ES6 为例)

const sort = require('immutable-sort');
const array = [1, 5, 2, 4, 3];
const sortedArray = sort(array);

你也可以这样写:

import sort from 'immutable-sort';
const array = [1, 5, 2, 4, 3];
const sortedArray = sort(array);

您看到的 import-from 是一种在 ES6 中包含 javascript 的新方法,并使您的代码看起来非常干净。我个人的最爱。

不可变排序不会改变源数组,而是返回一个新数组。使用const建议不可变的数据。

不适用于 Chrome 移动版 >= 88.0.4324.152
2021-03-21 14:05:42
另一个不可变的选择是使用 arr.slice().sort(...)
2021-04-03 14:05:42

这是@David Brainer-Bankers 答案的略微修改版本,它按字符串或数字按字母顺序排序,并确保以大写字母开头的单词不会排在以小写字母开头的单词之上(例如“apple,Early”将按该顺序显示)。

function sortByKey(array, key) {
    return array.sort(function(a, b) {
        var x = a[key];
        var y = b[key];

        if (typeof x == "string")
        {
            x = (""+x).toLowerCase(); 
        }
        if (typeof y == "string")
        {
            y = (""+y).toLowerCase();
        }

        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
}
sort 可以接受任何正数或负数作为有效返回值。你需要额外的计算来强制它为 1,0,-1 是不需要的。你把一个简单的返回值复杂化了。最好不要添加没有任何作用的额外计算。
2021-03-25 14:05:42
如果 a[key] 和 b[key] 不是两个字符串,则建议的解决方案可能会出错。我建议用 y = (""+y).toLowerCase() 替换 y=y.toLowerCase()
2021-04-03 14:05:42

使用下划线 js 或 lodash,

var arrObj = [
    {
        "updated_at" : "2012-01-01T06:25:24Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-09T11:25:13Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-05T04:13:24Z",
        "foo" : "bar"
    }
];

arrObj = _.sortBy(arrObj,"updated_at");

_.sortBy() 返回一个新数组

参考http://underscorejs.org/#sortBy和 lodash 文档https://lodash.com/docs#sortBy