如何在属性不一致时基于属性对JS对象列表进行排序

时间:2016-05-18 06:20:37

标签: javascript sorting

我有包含各种对象的列表。此列表中的一些对象具有日期字段(基本上从服务器返回给我,而不是日期对象),而对于其他对象,此字段为空。

我的要求是在顶部显示没有日期的对象,并且在按日期字段排序之后需要显示具有日期的对象。

对于没有日期排序的对象,也需要按字母顺序排序。

早些时候我正在使用

$scope.lists.sort(function (a, b) { 
    return new Date(a.date.split("-")[2], a.date.split("-")[1], a.date.split("-")[0]) - new Date(b.date.split("-")[2], b.date.split("-")[1], b.date.split("-")[0]); 
    });

但现在使用null日期字段,这将无效。所以无法找到任何东西,我写了这个逻辑:

{
    var datelists=[];
    var savelists =[];
    $scope.lists.forEach(function (t) {
        if (t.date !== null) {
            datelists.push(t);
        } else {
            savelists.push(t);
        }
    });
    datelists.sort(function (a, b) {
       return new Date(a.date.split("-")[2], a.date.split("-")[1], a.date.split("-")[0]) - new Date(b.date.split("-")[2], b.date.split("-")[1], b.date.split("-")[0]);
    });
    savelists.sort(function (a, b) {
        return a.name - b.name;
    });
    $scope.lists = [];
    $scope.lists = savelists.concat(datelists);
}

我不喜欢这种漫长的方法。我相信有一种优雅的方式来做到这一点。 我想知道我还有其他选择吗?

3 个答案:

答案 0 :(得分:1)

为避免拆分数组,请在日期和文本的主键和辅助键上对整个数组进行排序。使用obj.dateobj.text作为示例属性名称分别保存日期和排序文本:

function dateCompare( d, e)
{   // code to compare date strings
    // return -1 for date d before e
    //         0 for date d same as e
    //        +1 for date e before d
    // algorithm depends on server date string format but could start

    if( !d)
       return e ? -1 : 0; // d is empty
    if( !e)
       return 1;          // e is empty, d is not
    // ... compare date strings
}


function textCompare(s, t)
{   // code to compare string  values
    // return -1 for s < t
    //         0 for s == t
    //        +1 for t > s

    // algorithms vary according to requirements. 
}

function objCompare( a, b)
{  // return a non zero result of dateCompare, or the result of textCompare:

   return dateCompare(a.date, b.date) || textCompare( a.text, b.text);
}

$scope.lists.sort( objCompare);

概述了如何在不涉及应用程序细节的情况下进行此操作。将objCompare转换为内联匿名函数,并根据需要嵌套日期和文本比较支持函数(或内联代码),以匹配现有的编程风格。

答案 1 :(得分:0)

排序时你必须检查日期是否为空,是undefined还是正常日期(未经测试)

.sort(function (a, b) {
    // sort alphabetically
    if (typeof a.date == 'undefined' && typeof b.date != 'undefined') {
        return -1;
    } else if (typeof a.date != 'undefined' && typeof b.date == 'undefined') {
        return 1;
    } else if (typeof a.date == 'undefined' && typeof b.date == 'undefined') {
        return a.name.localeCompare(b.name);
    // move null to top
    } else if (a.date == null && b.date != null) {
        return -1;
    } else if (a.date != null && b.date == null) {
        return 1;
    } else if (a.date == null && b.date == null) {
        return 0;

    // both objects has date, sort by date.
    } else {
        var d1 = Date.parse(a.date);
        var d2 = Date.parse(b.date);

        return d1 - d2;
    }
})

答案 2 :(得分:0)

首先,您可以将date转换为ISO6801日期字符串。

如果提供了date,或者由空字符串替换的假值,则可以使用String#localeCompare。这会将空字符串排序到顶部。

如果日期相同或两者都没有日期,则按name排序。

$scope.lists.sort(function (a, b) {
    function date(s) {
        return s.replace(/(\d{2})-(\d{2})-(\d{4})/g, '$3-$2-$1');
    }

    return (date(a.date) || '').localeCompare(date(b.date) || '') ||
        a.name.localeCompare(b.name);
});