實務上 API 多半回傳 Object Array,但若想當做 Map 使用時 Object 會比較方便,因此常常需要將 Object Array 轉成 Object。
Version
Ramda 0.27.1
Imperative
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let f = a => {
let result = {}
for (let x of a)
result[x.title] = x.price
return result
}
f(data) // ?
第 3 行
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
data
內的 Object 有 title
與 price
,但由於想當 Map 使用,因此希望結果為以下 Object。
{ 'FP in JavaScript': 100,
'RxJS in Action': 200,
'Speaking JavaScript': 300 }
第 9 行
let f = arr => {
let result = {}
for (let x of arr)
result[x.title] = x.price
return result
}
Imperative 會使用 for
loop,因為結果為 Object,所以 result
初始值為 {}
。
在 for
loop 中使用 ECMAScript 獨家的 []
動態新增 property,最後回傳 result Object。
reduce()
import { reduce } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let f = reduce((ac, x) => ({...ac, [x.title]: x.price}), {})
f(data) // ?
由於 input 為 Array,回傳結果為 Object,型別完全不同,很適合 reduce()
。
第 9 行
let f = reduce((ac, x) => ({...ac, [x.title]: x.price}), {})
將累計的 ...ac
展開,再使用 {}
動態重新組合 object。
fromPairs()
import { pipe, map, props, fromPairs } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
pipe(
map(props(['title', 'price'])),
fromPairs
)(data) // ?
- 使用
map(props)
取得 value 部分 - 使用
fromPairs()
將 Nested Array 轉成 Object
plucks()
import { pipe, fromPairs } from 'ramda'
import { plucks } from 'wink-fp'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
pipe(
plucks(['title', 'price']),
fromPairs
)(data) // ?
也可使用 plucks()
取代 map(props)
。
Conclusion
- 實務上應先考慮 higher order function,若真的無招時,就是出大絕使用
reduce()
的時機