實務上常使用 Object Array,有時候必須在原本 Object 加上 Index,這種常見需求該如何實現呢 ?
Version
Ramda 0.27.1
mapIndex()
import { addIndex, map, pipe, pluck } from 'ramda'
let data = [
{ title: 'FP in JavaScript' },
{ title: 'RxJS in Action' },
{ title: 'Speaking JavaScript' }
]
let mapi = addIndex(map)
pipe(
pluck('title'),
mapi((x, i) => ({ key: i, title: x }))
)(data) // ?
第 3 行
let data = [
{ title: 'FP in JavaScript' },
{ title: 'RxJS in Action' },
{ title: 'Speaking JavaScript' }
]
data
原為只有 title
的 Object Array,想要變成帶有 key
的 Object Array。
第 9 行
let mapi = addIndex(map)
Ramda map()
的 callback 並沒有帶 index,必須使用 addIndex()
組合 map()
。
11 行
pipe(
pluck('title'),
mapi((x, i) => ({ key: i, title: x }))
)(data) // ?
- 使用
pluck()
取出title
- 使用
mapi()
回傳帶有key
的 Object Array
zipObj()
import { addIndex, map, pipe, pluck, pair, zipObj, flip } from 'ramda'
let data = [
{ title: 'FP in JavaScript' },
{ title: 'RxJS in Action' },
{ title: 'Speaking JavaScript' }
]
let mapi = addIndex(map)
pipe(
pluck('title'),
mapi(flip(pair)),
map(zipObj(['key', 'title']))
)(data) // ?
11 行
pipe(
pluck('title'),
mapi(flip(pair)),
map(zipObj(['key', 'title']))
)(data) // ?
若不追求 point-free,其實 mapi()
配合 arrow function 就能達成需求。
若要使 mapi()
也能 point-free,由於最終結果為 key
與 title
的 Object 只有兩個 property,可先使用 mapi()
轉成 Pair Array。
由於最終還是 Object Array,因此 map()
可使用 zipObj()
將兩個 array 合併成 Object。
Wink-fp
import { addIndex, map, pipe, pluck, pair, zipObj, flip } from 'ramda'
import { mapi } from 'wink-fp'
let data = [
{ title: 'FP in JavaScript' },
{ title: 'RxJS in Action' },
{ title: 'Speaking JavaScript' }
]
pipe(
pluck('title'),
mapi(flip(pair)),
map(zipObj(['key', 'title']))
)(data) // ?
mapi()
因為實務上經常使用,Wink-fp 已經提供 mapi()
。
Conclusion
- 若只要求結果正確,其實感受不到 Ramda 威力,在追求 point-free 下很多 arrow function 都能藉由 function 組合產生,這正是 Ramda 神奇之處