點燈坊

失くすものさえない今が強くなるチャンスよ

使用 sort() 根據日期排序

Sam Xiao's Avatar 2020-09-17

將結果依日期排序且最新日期在第一筆,也是實務上常見需求,由於 Date 特性,排序時並不像 Number、String 那樣簡單,須自行實作 Comparator Function。

Version

macOS Catalina 10.15.6
Ramda 0.27.1
Date-fp 5.0.3
Wink-fp 1.23.11

sort()

import { sort } from 'ramda'

let data = [
  { title: 'FP in JavaScript', release: '2016-06-18 07:43:14' },
  { title: 'RxJS in Action', release: '2017-08-04 03:24:18' },
  { title: 'Speaking JavaScript', release: '2017-03-24 17:08:39' }
]

sort((x, y) => y.release - x.relase, data) // ?

release 為各書的 發行日期,我們希望依發行日期 release 排序,且最新日期放在第一筆。

sort()
((a, a) → Number) → [a] → [a]
自行提供 comparator function 將 array 排序

(a, a) -> Number:自行提供 comparator function 比較

[a]:data 為 array

[a]:排序過後新 array

直覺會如處理 number 一樣,將兩數直接相減,但結果不如預期。

date000

發現根本沒有排序。

因為 release 為 string,直接相減為 NaN,因此排序失敗。

Date-fp

import { sort } from 'ramda'
import { diff } from 'date-fp'
import { toDate } from 'wink-fp'

let data = [
  { title: 'FP in JavaScript', release: '2016-06-18 07:43:14' },
  { title: 'RxJS in Action', release: '2017-08-04 03:24:18' },
  { title: 'Speaking JavaScript', release: '2017-03-24 17:08:39' }
]

// compare :: (a, a) -> Number
let compare = (x, y) => diff('seconds')(
  toDate(x.release), toDate(y.release)
)

sort(compare, data) // ?

應該先轉成 Date 之後,再使用 Date-fp 的 diff() 相減排序。

date003

Point-free

import { pipe, sort, useWith, prop } from 'ramda'
import { diff } from 'date-fp'
import { toDate } from 'wink-fp'

let data = [
  { title: 'FP in JavaScript', release: '2016-06-18 07:43:14' },
  { title: 'RxJS in Action', release: '2017-08-04 03:24:18' },
  { title: 'Speaking JavaScript', release: '2017-03-24 17:08:39' }
]

// getDate :: Object -> Date
let getDate = pipe(
  prop('release'), 
  toDate
)

// compare :: (a, a) -> Number
let compare = useWith(
  diff('seconds'), [getDate, getDate]
)

sort(compare, data) // ?

也可使用 useWith() 進一步將 compare() 也 point-free。

date005

Conclusion

  • Date 格式不能簡單相減,必須轉成 Date 之後使用 Date-fp 的 diff() 相減
  • 要將 String 轉成 Date,可使用 Wink-fp 的 toDate()

Reference

Ramda, sort()
Ramda, useWith()
Ramda, prop()
Date-fp, diff()