點燈坊

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

如何使用 pick() 與 evolve() 組合處理資料 ?

Sam Xiao's Avatar 2021-01-30

實務上從 API 取得資料時,常只需部分欄位,並對部分欄位加工處理,這種常見需求可用 pick() + evolve() 加以實現。

Version

Ramda 0.27.1

map()

import { pipe, map } from 'ramda'

let data = [
  { id: 1, title: 'FP in JavaScript', price: 100 },
  { id: 2, title: 'Programming Haskell', price: 200 },
  { id: 3, title: 'Speaking JavaScript', price: 300 }
]

pipe(
  map(x => ({
    title: x.title,
    price: x.price * 0.8
  }))
)(data) // ?

data 包含 idtitleprice 三個欄位,但我們只需要 titleprice,且 price 需打 8 折處理。

若使用 map() 會直接在 callback 回傳 Object,但會發現實際上做了兩件事情:

  • 只取得 titleprice
  • price 打八折

事實上可將這兩件事情分兩次處理。

evolve000

pick() + evolve()

import { pipe, map, pick, evolve, multiply } from 'ramda'

let data = [
  { id: 1, title: 'FP in JavaScript', price: 100 },
  { id: 2, title: 'Programming Haskell', price: 200 },
  { id: 3, title: 'Speaking JavaScript', price: 300 }
]

pipe(
  map(pick(['title', 'price'])),
  map(evolve({ price: multiply(0.8) }))
)(data) // ?
  • pick():先使用 pick() 只取得 titleprice 兩個欄位
  • evolve():再使用 evolve() 只對 price 打八折處理

由於 evolve() 內接 function,若需更複雜的計算,可先建立 curried function 並將 data 放在最後一個 argument,如此則可如 multiply() 一樣整合到 evolve() 內。

evolve001

Conclusion

  • map() 處理資料為常見需求,可使用 pick()evolve() 分兩步驟進行,可讀性更高

Reference

Ramda, pick()
Ramda, evolve()