若 array 中遍佈了一堆 0
,我們希望將 非 0
部分全部往前移,而 0
全部挪到最後,該如何實現呢 ?
Version
macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.253
Ramda 0.26.1
Wink-fp 0.1.2
Functional
let data = [0, 1, 4, 8, 0, 1];
let fn = arr => {
let arr0 = arr.filter(x => x !== 0);
let arr1 = arr.filter(x => x === 0);
return arr0.concat(arr1);
};
fn(data); // ?
分別使用 filter()
取得 非 0
與 0
的部分,最後使用 concat()
將兩個 array 合併。
Point-free
import { filter, concat, converge, equals, complement } from 'ramda';
let data = [0, 1, 4, 8, 0, 1];
let fn = converge(
concat, [
filter((complement(equals))(0)),
filter(equals(0))
]
);
fn(data); // ?
經觀察 concat()
為最後執行 function,且 concat()
的第一個 argument 與 第二個 argument 都必須經過同一個 arr
argument 轉換,符合 coverge()
要求。
filter()
的 callback 可藉由 equals()
與 complement(equals)
產生。
Wink-fp
import { filter, concat, converge, equals, complement } from 'ramda';
import { nequals } from 'wink-fp';
let data = [0, 1, 4, 8, 0, 1];
let fn = converge(
concat, [
filter(nequals(0)),
filter(equals(0))
]
);
fn(data); // ?
可改用 Wink-fp 的 nequls()
取代 complement(equals)
,語意更佳。
Conclusion
- 一個用 imperative 看似麻煩的問題,若使用 functional 解異常簡單,亦可使用 Ramda 的
converge()
與 Wink-fp 的nequals()
繼續重構
Reference
Ramda, concat()
Ramda, filter()
Ramda, converge()
Ramda, equals()
Ramda, complement