簡體   English   中英

使用多個鍵排序數組對象:Javascript

[英]Sort Array Object with Multiple Keys: Javascript

好吧,我有一個帶隨機值的數組對象,Ex。

var arr = [
    { id:1001, date:"20-02-2014", Name: 'demo1' },
    { id:1004, date:"13-02-2014", Name: 'demo0' },
    { id:1000, date:"10-02-2014", Name: 'demo14' },
    { id:1004, date:"16-02-2014", Name: 'demo10' },
    { id:1006, date:"22-02-2014", Name: 'demo111' },
    { id:1003, date:"28-02-2014", Name: 'demo16' },
    { id:1000, date:"28-01-2014", Name: 'demo12' },
    { id:1004, date:"28-01-2014", Name: 'demo01' },
    { id:1000, date:"08-01-2014", Name: 'demo41' },
    { id:1006, date:"08-01-2014", Name: 'demo91' }
]

我想先按鍵id然后按關鍵date排序這個數組,

輸出:

sorted_arr = [
 {"id":1000,"date":"08-01-2014","Name":"demo41"}, //group1
 {"id":1000,"date":"28-01-2014","Name":"demo12"}, //group1
 {"id":1000,"date":"10-02-2014","Name":"demo14"}, //group1 
 {"id":1001,"date":"20-02-2014","Name":"demo1"},  //group2
 {"id":1003,"date":"28-02-2014","Name":"demo16"}, //group3
 {"id":1004,"date":"28-01-2014","Name":"demo01"}, //group4
 {"id":1004,"date":"13-02-2014","Name":"demo0"},  //group4
 {"id":1004,"date":"16-02-2014","Name":"demo10"}, //group4
 {"id":1006,"date":"08-01-2014","Name":"demo91"}  //group5
 {"id":1006,"date":"22-02-2014","Name":"demo111"} //group5
]

我嘗試了幾個通用代碼來排序,

    // generic comparison function
    cmp = function(x, y){
      return x > y ? 1 : x < y ? -1 : 0; 
    };


    arr.sort(function(a, b){
       return cmp( 
          [cmp(a.id, b.id), cmp(a.date, b.date)], 
          [cmp(b.id, a.id), cmp(b.date, a.date)]
       );
    });

我提到了幾個例子SO示例,但沒有得到預期的輸出。 請建議我最好的方法來獲得這個。

無需創建Date對象,只需將日期字符串重新排序為可排序字符串,例如

此示例假定您的日期格式與DD-MM-YYYY並為日期排序創建YYYYMMDD

使用Javascript

var arr = [
    { id:1001, date:"20-02-2014", Name: 'demo1' },
    { id:1004, date:"13-02-2014", Name: 'demo0' },
    { id:1000, date:"10-02-2014", Name: 'demo14' },
    { id:1004, date:"16-02-2014", Name: 'demo10' },
    { id:1006, date:"22-02-2014", Name: 'demo111' },
    { id:1003, date:"28-02-2014", Name: 'demo16' },
    { id:1000, date:"28-01-2014", Name: 'demo12' },
    { id:1004, date:"28-01-2014", Name: 'demo01' },
    { id:1000, date:"08-01-2014", Name: 'demo41' },
    { id:1006, date:"08-01-2014", Name: 'demo91' }
];

var sorted = arr.sort(function (a, b) {
    return a.id - b.id || a.date.split('-').reverse().join('') - b.date.split('-').reverse().join('');
});

sorted.forEach(function (element) {
    console.log(JSON.stringify(element));
});

產量

{"id":1000,"date":"08-01-2014","Name":"demo41"}
{"id":1000,"date":"28-01-2014","Name":"demo12"}
{"id":1000,"date":"10-02-2014","Name":"demo14"}
{"id":1001,"date":"20-02-2014","Name":"demo1"} 
{"id":1003,"date":"28-02-2014","Name":"demo16"} 
{"id":1004,"date":"28-01-2014","Name":"demo01"} 
{"id":1004,"date":"13-02-2014","Name":"demo0"}
{"id":1004,"date":"16-02-2014","Name":"demo10"}
{"id":1006,"date":"08-01-2014","Name":"demo91"} 
{"id":1006,"date":"22-02-2014","Name":"demo111"}

jsFiddle上

如果對混合日期格式有任何疑慮,如@xdazz所討論的那樣,那么你可以通過自己檢查填充來改進。 按日期排序時,以下內容將創建格式“YYYYYYMMDD”。 在這個例子中沒有必要使用額外的年份填充,因為我正在取值的數值差異,但如果你選擇比較字符串那么它很重要。

function pad(s, n) {
    var v = '',
        i;

    for(i = 0; i < n - s.length; i += 1) {
        v += '0';
    }

    return v + s;
}

var sorted = arr.sort(function (a, b) {
    var idDiff = a.id - b.id;

    if (idDiff) {
        return idDiff;
    }

    var ordA = a.date.split('-').reverse(),
        ordB = b.date.split('-').reverse();

    ordA[0] = pad(ordA[0], 6);
    ordA[1] = pad(ordA[1], 2);
    ordA[2] = pad(ordA[2], 2);
    ordA = ordA.join('');
    ordB[0] = pad(ordB[0], 6);
    ordB[1] = pad(ordB[1], 2);
    ordB[2] = pad(ordB[2], 2);
    ordB = ordB.join('');
    return ordA - ordB;
});

jsFiddle上

如果你真的想使用Date對象,我建議如下。

var sorted = arr.sort(function (a, b) {
    var idDiff = a.id - b.id;

    if (idDiff) {
        return idDiff;
    }

    var ordA = a.date.split('-').reverse(),
        ordB = b.date.split('-').reverse();

    ordA[1] -= 1;
    ordB[1] -= 1;

    return new Date(Date.UTC.apply(undefined, ordA)).valueOf() -  new Date(Date.UTC.apply(undefined, ordB)).valueOf();
});

sorted.forEach(function (element) {
    console.log(JSON.stringify(element));
});

jsFiddle上

注意:這些示例不處理負數年份的日期,您還需要進行進一步修改。

首先與id進行比較,然后如果id相等則與date進行比較。 但由於您的日期格式無效,因此必須進行額外的工作才能讓Date識別。

sorted_arr = arr.sort(function(a, b) {
   return a.id - b.id || new Date(a.date.split('-').reverse().join('-')) - new Date(b.date.split('-').reverse().join('-'));
});

編輯:如果您保證在1位數月份和日期前面有零,那么您甚至可以不解析到目前為止:

sorted_arr = arr.sort(function(a, b) {
   return a.id - b.id || a.date.split('-').reverse().join('') - b.date.split('-').reverse().join('');
});

最好有一個日期操作lib momentjs來幫助。 你可以查看jsBin上的代碼

function compare(a, b){
   var idDiff = a.id - b.id;
   var adate = moment(a.date, "DD-MM-YYYY");
   var bdate = moment(b.date, "DD-MM-YYYY");
   var dateDiff = adate.diff(bdate);
   return idDiff || dateDiff;
}

var sortedArr = arr.sort(compare);
console.log(sortedArr);

您可以使用Alasql庫按兩個屬性對數組進行排序:

var res = alasql('SELECT *, mid(date,7,4)+mid(date,4,2)+mid(date,1,2) AS ndate \
    FROM ? ORDER BY id, ndate',[arr]);

在jsFiddle上試試這個例子。

這里“mid(date,7,4)+ mid(date,4,2)+ mid(date,1,2)”用於將日期從'28 -11-2014'轉換為排序鍵,如'20141128' 。

想出了這個使用underscore.js&它的sortBy

var sorted_array = _(arr).chain().sortBy(function(o) {
    return o.date.split('-').reverse().join(); 
}).sortBy(function(o) {
    return o.id;
}).value();

首先對日期進行排序,然后id將為您提供按預期排序的列表。

的jsfiddle

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM