【问题标题】:Sort array by date gives unexpected results按日期排序数组会产生意想不到的结果
【发布时间】:2015-03-16 18:35:37
【问题描述】:

这听起来是一个简单的问题,但我花了我的星期天试图找出我的实现有什么问题,所以我将它发布到 SO 作为最后的手段。

我有一个从服务器接收数据结构的 javascript 应用程序。服务器端出于性能原因发送未排序的数据。

这是接收数据的javascript代码的sn-p:

    var seriesRawDataArray = ko.observableArray();
    ...
    analyticscontext.series(seriesRawDataArray).done(function () {
        renderSeries();
    });

analyticscontext 模块使用 ajax 查询数据:

function series(seriesData) {
    return $.ajax({
        url: "/api/analytics/series",
        type: "GET",
        success: function (data) {
            return seriesData(data);
        }
    });
}

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

问题

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

注意最后未排序的项目。 seriesRawDataArray.sort 似乎对原始数组没有影响,无论我在排序方法中进行什么更改,它都不会排序。输出总是:

请注意此处未排序的元素。 我正在使用的库和数据绝对不是问题,因为 jsfiddle 工作得很好! 这段代码有问题吗?

【问题讨论】:

标签: javascript arrays sorting knockout.js


【解决方案1】:

简短回答

您应该返回两个日期之间的差异,而不是布尔值:

// sort the data by date using moment.js
seriesRawDataArray.sort(function (left, right) {
    return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
});

为什么

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

传递给 sort 的匿名函数用作排序函数本机实现的比较器。

但是,您的负值不一定是-1,您的正值不一定是+1。因此,在对数字进行排序时,可以改为使用快捷方式:

yourArray.sort(function (a, b) {
    return a - b
})

在 JavaScript 中,减去两个日期会将它们强制转换为数字,这就是为什么我们可以使用 return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))

(代替直接减法-,此方法使用moment.js库中的moment.prototype.diff

但是,在您的代码中,您返回了diff &gt; 0,它可以是truefalse。由于类型强制,JavScript 将true 读作1false 读作0。这意味着您的排序函数将永远不会返回-1。因此,您的元素将无法正确排序。

【讨论】:

  • 请注意,您可能需要过滤掉无效的值。 if(a._isValid &amp;&amp; b._isValid) 排序 Moment Js 日期时。
  • 有什么理由需要.utc
【解决方案2】:
let sortedDates = dates.sort(function(a, b){
  return moment(b).format('X')-moment(a).format('X')
});

由于 moment 可以格式化有效日期,最好的方法是使用排序方法 javascript,所以在将日期格式化为时间戳时,基本上是按数字排序。

参考文献:

http://www.momentjs.com/docs/#/displaying/format

http://www.w3schools.com/jsref/jsref_sort.asp

【讨论】:

    猜你喜欢
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 2016-06-20
    相关资源
    最近更新 更多