Javascript 按日期对数组进行排序会产生意想不到的结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28013045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sort array by date gives unexpected results
提问by GETah
This will sound as an easy problem but I spent my Sunday trying to figure out what's wrong with my implementation described below so I am posting it to SO as a last resort.
这听起来是一个简单的问题,但我花了我的星期天试图找出下面描述的我的实现有什么问题,所以我将它发布到 SO 作为最后的手段。
I have a javascript application that receives data structures from a server. The server side sends the data unsorted for performance reasons.
我有一个从服务器接收数据结构的 javascript 应用程序。服务器端出于性能原因发送未排序的数据。
Here is a snippet of the the javascript code receiving data:
这是接收数据的javascript代码片段:
var seriesRawDataArray = ko.observableArray();
...
analyticscontext.series(seriesRawDataArray).done(function () {
renderSeries();
});
The analyticscontextmodule queries the data using ajax:
该analyticscontext模块使用ajax查询数据:
function series(seriesData) {
return $.ajax({
url: "/api/analytics/series",
type: "GET",
success: function (data) {
return seriesData(data);
}
});
}
The renderSeriesperforms a sort on the data before rendering it:
在renderSeries执行渲染它之前的数据排序:
// Sort the data by date using moment.js
seriesRawDataArray.sort(function (left, right) {
var leftDate = moment.utc(left.timeStamp);
var rightDate = moment.utc(right.timeStamp);
var diff = leftDate.diff(rightDate);
return diff > 0;
});
PROBLEM
问题
Here is a data sample I receive from my server:

这是我从服务器收到的数据样本:

Notice the unsorted items at the end.
the seriesRawDataArray.sortseem to have no effect on the original array which does not get sorted no matter what I change in the sorting method. The output is always:
注意最后未排序的项目。在seriesRawDataArray.sort似乎有原来的阵列,它没有得到不管我在排序方法更改排序没有影响。输出总是:


Notice the unsorted elements here. The libraries I am using and the data is definitely not the problem as this jsfiddleworks just fine! Is there something wrong with this code?
注意这里的未排序元素。我正在使用的库和数据绝对不是问题,因为这个jsfiddle工作得很好!这段代码有什么问题吗?
回答by royhowie
short answer
简答
You should return the difference between the two dates, not a boolean:
您应该返回两个日期之间的差异,而不是布尔值:
// sort the data by date using moment.js
seriesRawDataArray.sort(function (left, right) {
return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
});
why
为什么
Array.prototype.sortexpects a negative, zero, or positive value to be returned. Generally, you'll write a sort function like this:
Array.prototype.sort期望返回负值、零值或正值。通常,您会编写这样的排序函数:
yourArray.sort(function (a, b) {
if (a < b) { // a comes first
return -1
} else if (b < a) { // b comes first
return 1
} else { // equal, so order is irrelevant
return 0 // note: sort is not necessarily stable in JS
}
})
The anonymous function passed to sort serves as the comparator for the native implementation of the sort function.
传递给 sort 的匿名函数用作 sort 函数本机实现的比较器。
However, your negative value doesn't have to be -1and your positive value doesn't have to be +1. Therefore, when sorting numbers, you can instead use the shortcut:
但是,负值不一定是-1,正值也不一定是+1。因此,在对数字进行排序时,您可以改为使用快捷方式:
yourArray.sort(function (a, b) {
return a - b
})
In JavaScript, subtracting two dates coerces them both into numbers, which is why we could use return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
在 JavaScript 中,减去两个日期会将它们强制转换为数字,这就是为什么我们可以使用 return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
(instead of direct subtraction -, this method uses moment.prototype.difffrom the moment.jslibrary)
(而不是直接减法-,此方法使用moment.prototype.diff从所述moment.js库)
However, in your code, you returned diff > 0, which can be either trueor false. Because of type coercion, JavScript will read trueas 1and falseas 0. This means your sort function will never return -1. Therefore, your elements will not be sorted correctly.
但是,在您的代码中,您返回了diff > 0,它可以是true或false。因为类型强制的,JavScript将阅读true作为1和false作为0。这意味着您的排序函数永远不会返回-1。因此,您的元素将无法正确排序。
回答by Ylli Gashi
let sortedDates = dates.sort(function(a, b){
return moment(b).format('X')-moment(a).format('X')
});
Since moment can format valid dates the best way is to use the sort method javascript, so when formatting the date to timestamp, basically you sort by number.
由于 moment 可以格式化有效日期,因此最好的方法是使用 sort 方法 javascript,因此在将日期格式化为时间戳时,基本上是按数字排序。
References:
参考:
http://www.momentjs.com/docs/#/displaying/format
http://www.momentjs.com/docs/#/displaying/format

