點燈坊

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

使用 sort() 自訂排序

Sam Xiao's Avatar 2020-09-16

Ramda 的 sort() 與 ECMAScript 內建的 Array.prototype.sort() 非常類似,都需自行提供 Comparator Function,唯 sort() 是無 Side Effect 版本。

Version

macOS Catalina 10.15.6
Ramda 0.27.1

Ramda

import { sort } from 'ramda'

let data = [3, 4, 2, 1]

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

Ascend 為 sort() 搭配 x - y;而 descend 為 y - x

sort()
((a, a) → Number) → [a] → [a]
將 array 根據 comparator function 加以排序

(a, a) -> Number:comparator function,若第一個參數比第二個參數小,傳回 < 0,也就是 ascend;若第一個參數比第二個參數大,傳回 > 0,也就是 descend,若相等則傳回 = 0

[a]:data 為 array

[a]:回傳新 array,型別完全相同,只是順序不同

Q:Ramda 的 sort() 看起來與 ECMAScript 原生的 Array.prototype.sort() 似乎一樣 ?

乍看之下似乎一樣,但仍有兩點不同:

  1. Array.prototype.sort() 的 comparator function 可省略,預設為 ascend。
  2. Array.prototype.sort() 為 side effect 寫法,會直接更改原本 array;而 Ramda 的 sort() 沒有 side effect,會傳回新 array

sort000

ascend()

import { sort, ascend } from 'ramda'

let data = [3, 4, 2, 1]

sort(ascend(Number), data) // ?

若常常不知道該 x - y 還是 y - x,可直接使用 ascend()descend() 產生 comparator function。

ascend()
Ord b => (a → b) → a → a → Number
產生 ascend comparator function

descend()
Ord b => (a → b) → a → a → Number
產生 descend comparator function

sort001

Object

import { sort } from 'ramda'

let data = [
  { title: 'FP in JavaScript', price: 300 },
  { title: 'RxJS in Action', price: 400 },
  { title: 'Speaking JavaScript', price: 200 },
  { title: 'JavaScript: The Good Parts', price: 100 },
]

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

sort() 提供 comparator function,描述該用什麼 property 做比較。

sort002

descend()

import { sort, descend, prop } from 'ramda'

let data = [
  { title: 'FP in JavaScript', price: 300 },
  { title: 'RxJS in Action', price: 400 },
  { title: 'Speaking JavaScript', price: 200 },
  { title: 'JavaScript: The Good Parts', price: 100 },
]

sort(descend(prop('price')), data) // ?

sort() 的 comparator function,也可改用 ascend()prop() 來組合使之 point-free。

sort003

Conclusion

  • sort() 最接近 Array.prototype.sort(),唯 Ramda 的 sort() 不可省略 comparator function,且對原來 Array 無 side effect
  • 可使用 ascend()descend()prop() 等產生 callback function 達成 point-free

Reference

Ramda, sort()
Ramda, ascend()
Ramda, descend()
Ramda, prop()