實務上我們常需判斷 Array 是否 全部不
符合某條件,若都不存在則傳回 true
,否則傳回 false
。
Version
macOS Catalina 10.15
VS Code 1.39.2
Quokka 1.0.256
ECMAScript 2015
Ramda 0.26.1
Imperative
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let none = fn => arr => {
for (let x of arr) {
if (fn(x)) return false
}
return true
}
none(x => x.price === 400)(data) // ?
建立 none()
,Imperative 會使用 for
loop 搭配 if
判斷,若符合條件就直接回傳 false
,若都不符合條件則回傳 true
。
reduce()
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let none = fn => arr => arr.reduce((a, v) => a && !fn(v), true)
none(x => x.price === 400)(data) // ?
由於結果為單一 boolean,因次特別適合使用 reduce()
產生。
Functional
import { compose, any, complement } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let none = compose(complement, any)
none(x => x.price === 400)(data) // ?
其實仔細想一想,none()
不就是 not any()
嗎 ? 因此我們也可以將 complement()
與 any()
組合產生 none()
。
Ramda
import { none } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
none(x => x.price === 400)(data) // ?
Ramda 已經內建 none()
,可直接使用。
none()
(a -> Boolean) -> [a] -> Boolean
判斷 array 中資料是否全部不符合條件
(a -> Boolean)
: 判斷條件 predicate
[a]
:data 為 array
Boolean
:回傳比較結果
Point-free
import { none, propEq } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
none(propEq('price')(400))(data) // ?
none()
的 callback 也可改用 propEq()
產生,語意更佳。
Function Composition
import { none, propEq, compose } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let fn = compose(none, propEq('price'))
fn(400)(data) // ?
亦可使用 compose()
將 propEq()
與 none()
組合起來。
Conclusion
- ECMAScript 並沒有內建
none()
- 由於結果為單一 boolean,因此適合使用
reduce()
產生 none()
也可以使用any()
組合出來,再次見證 function composition 威力none()
的 callback 也可用 Ramda 的 function 產生,point-free 更精簡,且可讀性更高- 當 callback 也 point-free 後,就更能看出 function composition 雛形,可使用
compose()
將none()
與 callback 組合起來
Reference
MDN, Array.prototype.reduce()
Ramda, none()
Ramda, any()
Ramda, complement()