当属性不一致时,如何根据属性对JS对象列表进行排序

How to sort a JS object list based on a property when the property is not consistent

本文关键字:属性 对象 JS 列表 排序 不一致 何根      更新时间:2023-09-26

我有一个包含各种对象的列表。这个列表中的一些对象有一个日期字段(它基本上是从服务器以字符串的形式返回给我的,而不是日期对象),而对于其他对象,这个字段是空的。

我的要求是在顶部显示没有日期的对象,而那些有日期的对象需要按日期字段排序后显示。

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

早些时候我使用

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

但现在有了空日期字段,这就不起作用了。所以找不到任何东西,我写了这样的逻辑:

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

我不喜欢这种冗长的方法。我相信有一种优雅的方法可以做到这一点。我想知道我还有什么其他选择?

为了避免拆分数组,请根据日期和文本的主键和辅键对整个数组进行排序。使用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转换为具有嵌套日期和文本比较支持函数(或内联代码)的内联匿名函数,以匹配现有编程风格。

排序时,必须检查日期是否为空、是否为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;
    }
})

首先,您可以将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);
});