Ramda 之 pickBy()
栏目: JavaScript · 发布时间: 5年前
内容简介:Ramda 之WebStorm 2018.3.3Quokka 1.0.136
Ramda 之 pick()
與 pickAll()
都只能直接指定 Object 要擷取的 Property,若想要根據自訂條件選擇 Property,就只能靠 pickBy()
,且可再將 pickBy()
與其他 function 組合成新的 function,如此可讀性更高。
Version
WebStorm 2018.3.3
Quokka 1.0.136
Ramda 0.26.1
根據 Value 決定 Property
Non Point-free
import { map, pickBy, includes } from 'ramda'; const data = [ { id: 1, title: 'Functional Programming in JavaScript', year: 2016 }, { id: 2, title: 'RxJS in Action', year: 2017 }, { id: 3, title: 'Speaking JavaScript', year: 2014 }, ]; const getBooks = map(pickBy(v => includes('JavaScript', v))); console.dir(getBooks(data));
若我們不確定要擷取 object 哪個 property,而是要根據 自訂條件
來決定,此時就要使用 pickBy()
,自行傳入 predicate function。
若需求是 object 的 value 含有 JavaScript
字眼,則擷取該 property 的 object。
pickBy()
((v, k) → boolean) → {k: v} → {k: v}
根據傳入的 predicate function,回傳新的符合條件 property 的 object
((v, k) -> boolean)
:條件的 predicate function,注意其第一個參數為 value,第二個參數為 key
{k: v}
:data 為 object
{k: v}
:回傳符合條件 property 的 object
因為需求是 根據 value 決定 property
,因此 pickBy()
的 callback 只需第一個參數即可。
includes()
a -> [a] -> boolean
若 value 存在於 array 內時,則傳回 true
,否則傳回 false
因此將 v
傳入 includes()
第二個參數。
這種寫法是 OK 的,唯 pickBy()
的 callback 還有 v
參數,所以並不算 Point-free。
Point-free
import { map, pickBy, includes } from 'ramda'; const data = [ { id: 1, title: 'Functional Programming in JavaScript' }, { id: 2, title: 'RxJS in Action' }, { id: 3, title: 'Speaking JavaScript' }, ]; const getBooks = map(pickBy(includes('JavaScript'))); console.dir(getBooks(data));
當 includes()
只傳進第一個參數時,將回傳 [a] -> boolean
,正好與 map()
的 callback signature 相同,因此可以使用 includes('JavaScript')
取代 v => includes('JavaScript', v)
,如此就將 v
幹掉了達成 Point-free。
import { map, pickBy, includes, compose } from 'ramda'; const data = [ { id: 1, title: 'Functional Programming in JavaScript' }, { id: 2, title: 'RxJS in Action' }, { id: 3, title: 'Speaking JavaScript' }, ]; const pickValueIncludes = compose( pickBy, includes, ); const getBooks = map(pickValueIncludes('JavaScript')); console.dir(getBooks(data));
map()
的 callback 由 pickBy(includes('JavaScript'))
構成,這種 f(g(x))
的寫法,可讀性似乎不佳。
事實上這種 f(g(x))
形式,正是典型的 Compose Function,最適合使用 compose()
先建立新的 function。
第 9 行
const pickValueIncludes = compose( pickBy, includes, );
將 includes()
與 pickBy()
組合成新的 pickValueIncludes()
,注意沒有任何參數,此為 Point-free。
14 行
const getBooks = map(pickValueIncludes('JavaScript'));
map()
的 callback 使用新的 pickValueIncludes()
並傳入 JavaScript
,如此寫法可讀性甚佳,可以很明確得知是從 value 判斷是否包含 JavaScript
,這就是 Function Composition 偉大之處。
根據 Key 決定 Property
Non Point-free
import { map, pickBy, includes } from 'ramda'; const data = [ { id: 1, title: 'Functional Programming in JavaScript' }, { id: 2, title: 'RxJS in Action' }, { id: 3, title: 'Speaking JavaScript' }, ]; const getBooks = map(pickBy((v, k) => includes('it', k))); console.dir(getBooks(data));
若需求是 object 的 key 含有 it
字眼,則擷取該 property 的 object。
由於 pickBy()
的 callback 中, k
是在第二個參數,因此 (v, k)
都必須使用,再將 k
傳給 includes()
。
同樣地這種寫法也沒有任何問題,只是 pickBy()
的 callback 包含 (v, k)
,因此不算 Point-free。
Point-free
import { map, pickBy, includes, flip, compose } from 'ramda'; const data = [ { id: 1, title: 'Functional Programming in JavaScript' }, { id: 2, title: 'RxJS in Action' }, { id: 3, title: 'Speaking JavaScript' }, ]; const pickKeyIncludes = compose( pickBy, flip, includes, ); const getBooks = map(pickKeyIncludes('it')); console.dir(getBooks(data));
根據之前經驗,我們學會了組合 includes()
與 pickBy()
成為一個新 function 當作 map()
的 callback,理論上在這裡也可如法泡製。
但 includes()
回傳的 signature 為 [a] -> boolean
,也就是 data 在第一個參數,但現在需求是 key,在 pickBy()
的 callback 是第二個參數,因此要使用 flip()
將第一個參數對調成第二參數的新 function,才能傳給 pickBy()
。
如此 map()
的 callback 就能使用新的 pickKeyIncludes('it')
,語意非常清楚,這就是 Function Composition 的魔力。
Conclusion
-
pickBy()
讓我們可以自己傳入 predicate function,遠比pick()
或pickAll()
更有彈性 - 可將
map()
的 callback 先compose()
成新的 function,如此可讀性更高,若 signature 不從人願,可再使用flip()
加以轉換
Reference
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。