filter()
與 reject()
都能各自回傳 符合條件
與 不符合條件
資料,若想同時回傳兩者則要使用 partition()
。
Version
macOS Catalina 10.15
VS Code 1.39.2
Quokka 1.0.258
Ramda 0.26.1
Imperative
import { includes } from 'ramda';
let data = [
'FP in JavaScript',
'RxJS in Action',
'Speaking JavaScript'
];
let partition = pred => arr => {
let filtered = [];
let rejected = [];
for(let x of arr)
pred(x) ? filtered.push(x) : rejected.push(x);
return [filtered, rejected];
};
let fn = v => partition(includes(v));
console.dir(fn('JavaScript')(data));
若想同時回傳包含 JavaScript
與不包含 JavaScript
資料,且在各自 array,我們可建立 partition()
:
使用
filter()
建立filtered
array使用
reject()
建立rejected
array最後使用
[]
將filtered
與rejected
組合成新 array
Array.prototype.reduce()
import { includes } from 'ramda';
let data = [
'FP in JavaScript',
'RxJS in Action',
'Speaking JavaScript'
];
let partition = pred => arr =>
arr.reduce((a, x) => {
let [filterd, rejeccted] = a;
pred(x) ? filterd.push(x) : rejeccted.push(x);
return a;
}, [[], []]);
let fn = v => partition(includes(v));
console.dir(fn('JavaScript')(data));
回傳為單一 array 且以 for
loop 實現,因此也可使用 Array.prototype.reduce()
實現。
let [filterd, rejeccted] = a;
以 ES6 的 array destructuring 拆解成 filtered
array 與 rejected
array。
pred(x) ? filterd.push(x) : rejeccted.push(x);
以 pred(x)
判斷,各自對 filtered
array 與 rejected
array 做 push。
return a;
由於 array destructuring 的 filtered
與 rejected
是 reference,因此 a
array 已經包含最新結果,直接回傳即可。
Functional
import { includes, juxt, filter, reject } from 'ramda';
let data = [
'FP in JavaScript',
'RxJS in Action',
'Speaking JavaScript'
];
let partition = juxt([filter, reject]);
let fn = v => partition(includes(v));
console.dir(fn('JavaScript')(data));
由於 partition()
回傳為 array,且各 element 又各由 filter()
與 reject()
,剛好適合使用 juxt()
將兩者組合起來。
Ramda
import { partition, includes } from 'ramda';
let data = [
'FP in JavaScript',
'RxJS in Action',
'Speaking JavaScript'
];
let fn = v => partition(includes(v));
console.dir(fn('JavaScript')(data));
Ramda 已經提供 partition()
,可直接使用。
partition()
Filterable f => (a -> Boolean) -> f a -> [f a, f a]
同時回傳 filter() 與 reject() 資料
(a -> Boolean)
:判斷條件 predicate
f a
:data 為 Filterable
[f a, f a]
:新的 array 同時包含 filter()
與 reject()
結果
Function Composition
import { partition, includes, compose } from 'ramda';
let data = [
'FP in JavaScript',
'RxJS in Action',
'Speaking JavaScript'
];
let fn = compose(partition, includes);
console.dir(fn('JavaScript')(data));
也可使用 compose()
將 includes()
與 partition()
組合起來使 fn()
point-free。
Conclusion
partition()
不只適用於 array,也適用於 object 或有filter()
method 的 object
Reference
MDN, Array.prototype.reduce()
Ramda, partition()
Ramda, filter()
Ramda, reject()
Ramda, juxt()
Ramda, includes()