按date值的单个键排列对象数组

我有一个包含几个键值对的数组,我需要根据'updated_at'对它们进行sorting:

[ { "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" } ] 

什么是最有效的方法呢?

你可以使用Array.sort

这是一个(未经testing)的例子:

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

我已经在这里回答了一个非常类似的问题: 简单的函数来sorting对象的数组

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

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

这里有一个稍微修改过的@David Brainer-Bankers版本, 可以用string或数字来按字母顺序sorting,并确保以大写字母开头的单词不以上面的小写字母开头(例如“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)); }); } 

Array.sort()方法就地排列数组的元素并返回数组。 Array.sort()要小心,因为它不是不可变的 。 对于不可变的sorting使用immutable-sort 。

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

对于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()不关心返回数字是什么。 它只关心返回值是正值,负值还是零。

对于不可变的sorting:(例如在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); 

从你看到的导入是一个新的方式来在ES6中包含JavaScript,并使您的代码看起来非常干净。 我个人最喜欢的

不变的sorting不会改变源数组,而是返回一个新的数组。 build议在不可变数据上使用const

使用下划线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

除非您将客户端限制在最新的和最好的浏览器上,否则通过ISO格式化的date进行sorting可能会很昂贵,因为它们可以通过date分析string来创build正确的时间戳。

如果你确定你的input,并且你知道它总是yyyy-mm-ddThh:mm:ss和GMT(Z),你可以从每个成员中提取数字,并将它们比较为整数

 array.sort(function(a,b){ return a.updated_at.replace(/\D+/g,'')-b.updated_at.replace(/\D+/g,''); }); 

如果date的格式可能不同,那么您可能需要为iso挑战的人添加一些内容:

 Date.fromISO: function(s){ var day, tz, rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/, p= rx.exec(s) || []; if(p[1]){ day= p[1].split(/\D/).map(function(itm){ return parseInt(itm, 10) || 0; }); day[1]-= 1; day= new Date(Date.UTC.apply(Date, day)); if(!day.getDate()) return NaN; if(p[5]){ tz= (parseInt(p[5], 10)*60); if(p[6]) tz+= parseInt(p[6], 10); if(p[4]== '+') tz*= -1; if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz); } return day; } return NaN; } if(!Array.prototype.map){ Array.prototype.map= function(fun, scope){ var T= this, L= T.length, A= Array(L), i= 0; if(typeof fun== 'function'){ while(i< L){ if(i in T){ A[i]= fun.call(scope, T[i], i, T); } ++i; } return A; } } } } 

另一种更加math的方法是做同样的事情,但时间更短

 arr.sort(function(a, b){ var diff = new Date(a.updated_at) - new Date(b.updated_at); return diff/(Math.abs(diff)||1); }); 

或者在光滑的lambda箭头样式中:

 arr.sort((a, b) => { var diff = new Date(a.updated_at) - new Date(b.updated_at); return diff/(Math.abs(diff)||1); }); 

这个方法可以用任何数字input来完成

你可以创build一个闭包,并通过这种方式, 这是我的例子工作

 $.get('https://data.seattle.gov/resource/3k2p-39jp.json?$limit=10&$where=within_circle(incident_location, 47.594972, -122.331518, 1609.34)', function(responce) { var filter = 'event_clearance_group', //sort by key group name data = responce; var compare = function (filter) { return function (a,b) { var a = a[filter], b = b[filter]; if (a < b) { return -1; } else if (a > b) { return 1; } else { return 0; } }; }; filter = compare(filter); //set filter console.log(data.sort(filter)); }); 

有了ES2015支持,可以通过以下方式完成:

 foo.sort((a, b) => a.updated_at < b.updated_at ? -1 : 1)