JSON陣列排序

Q:a = [{id1: '...', time: '...', desc: '....'}, {id2....},....],怎麼依據‘time’來排序array?

A:當然可以!這是在 JavaScript 中處理資料時一個非常常見且重要的操作。

要根據 'time' 這個字串來排序陣列,最推薦的方法是使用 Array.prototype.sort() 方法,並提供一個自訂的「比較函式」(compare function) 來告訴 JavaScript 如何比較兩個時間字串。

核心思想:直接比較 '05:00''10:00' 這樣的字串是不可靠的。我們需要將它們轉換成可比較的格式,例如 Date 物件或總秒數,然後再進行比較。

假設你的資料如下:

let timers = [
    { id: 'id2', time: '10:30', desc: '做簡報' },
    { id: 'id1', time: '01:00', desc: '運動' },
    { id: 'id4', time: '00:15', desc: '喝水' },
    { id: 'id3', time: '05:00', desc: '冥想' }
];
  

方法一:轉換為 Date 物件進行比較 (最穩健、最推薦)

這是最可靠的方法,因為 Date 物件可以準確地處理時間,並且可以直接相減得到一個數字,完美適用於 sort 方法。

升序排序 (時間由小到大)

    // 為了比較,我們創建一個基於相同日期的 Date 物件
    const timeA = new Date(`1970-01-01T${a.time}`);
    const timeB = new Date(`1970-01-01T${b.time}`);
    
    // Date 物件可以直接相減,結果為毫秒差,正好是 sort 需要的
    // 如果 timeA < timeB,結果為負數,a 排在前面
    // 如果 timeA > timeB,結果為正數,b 排在前面
    return timeA - timeB;
});

console.log(timers);
  

排序後結果:

    { id: 'id4', time: '00:15', desc: '喝水' },
    { id: 'id1', time: '01:00', desc: '運動' },
    { id: 'id3', time: '05:00', desc: '冥想' },
    { id: 'id2', time: '10:30', desc: '做簡報' }
]
  

降序排序 (時間由大到小)

只需要把 ab 的位置換一下即可。

    const timeA = new Date(`1970-01-01T${a.time}`);
    const timeB = new Date(`1970-01-01T${b.time}`);
    
    // b - a 即可得到降序結果
    return timeB - timeA;
});
  

程式碼解釋

  • array.sort(compareFunction): sort 方法會接收一個函式,這個函式需要接收兩個參數 (通常命名為 ab),代表陣列中正在被比較的兩個元素。

  • new Date('1970-01-01T' + a.time): 我們在時間字串前加上一個固定的日期 '1970-01-01T',是為了創建一個有效的 Date 物件讓 JavaScript 解析。因為我們只關心時間部分,所以日期是哪天並不重要,只要所有元素的比較基準都一樣即可。

  • return timeA - timeB;: 這是 sort 的核心。

    • 如果回傳值 < 0a 會被排在 b 前面。

    • 如果回傳值 > 0b 會被排在 a 前面。

    • 如果回傳值 = 0ab 的相對位置不變。
      Date 物件相減的結果(毫秒差)完美地符合這個要求。


方法二:直接使用字串比較 (較簡單,但有前提)

如果你非常確定你的時間格式永遠是 hh:mm (例如 01:00 而不是 1:00),也就是說小時和分鐘都必定是兩位數,那麼你可以直接比較字串。

這是因為在這種固定格式下,字串的字典序排序結果會和時間順序一致。

升序排序 (使用 localeCompare)

  

降序排序

  

為什麼這個方法有風險?
如果你的資料出現了 time: '5:00'time: '10:00',字串比較會認為 '5:00' 大於 '10:00' (因為第一個字元 '5' > '1'),這就完全錯了。

localeCompare() 是比較字串的標準方法,比使用 >< 更可靠,但它依然是基於字串的比較。


總結

方法優點缺點推薦場景
轉換為 Date 物件最穩健、最可靠。不受字串格式影響,能正確處理各種情況。程式碼稍微長一點點。所有情況,特別是當你不完全確定資料格式的純潔性時,這是最佳實踐。
直接比較字串非常簡潔,程式碼只有一行。有前提條件。只在時間格式嚴格統一(例如 hh:mm 補零)時才有效。快速開發或你完全能掌控資料來源和格式的情況。

為了你的擴充功能的穩定性,強烈建議你使用方法一 (轉換為 Date 物件)

留言

這個網誌中的熱門文章

Offscreen Canvas

外部網頁新增 Google 日曆行程(URL模板)

計算 Canvas 文字最大字體