takeLast()
只能取得 Array 固定最後筆資料,若想自行提供自訂條件 Predicate,就得使用 takeLastWhile()
。
Version
macOS Mojave 10.14.5
VS Code 1.36.1
Quokka 1.0.233
Ramda 0.26.1
let data = [2, 4, 1, 3];
// takeLastWhile :: (a → Boolean) → [a] → [a]
let takeLastWhile = pred => arr => {
let result = [];
for(let i = arr.length - 1; i >= 0; i--) {
if (pred(arr[i]))
result.unshift(arr[i]);
else
break;
}
return result;
};
takeLastWhile(x => x % 2)(data); // ?
takeLastWhile()
意義為當 predicate 為 true
時從最後取得 element,直到 false
時停止取得。
建立 takeLastWhile()
,imperative 會先建立回傳 result
array,i
從最後 index 開始,當 predicate 成立時,從 result
前面塞進 element,不成立馬上離開 for
loop,最後回傳 result
。
Functional
import { pipe, reverse, takeWhile } from 'ramda';
let data = [2, 4, 1, 3];
// takeLastWhile :: (a → Boolean) → [a] → [a]
let takeLastWhile = pred => pipe(
reverse,
takeWhile(pred),
reverse
);
takeLastWhile(x => x % 2)(data); // ?
若一開始不知道 takeLastWhile()
也沒關係,可藉由已知的 takeWhile()
加以組合:
- 使用
reverse()
將 array 反轉 - 使用
takeWhile()
根據 predicate 條件取得資料 - 使用
reverse()
再將 array 反轉
最後使用 pipe()
組合所有 function,非常清楚。
Point-free
import { pipe, reverse, takeWhile, useWith, identity } from 'ramda';
let data = [2, 4, 1, 3];
// takeLastWhile :: (a → Boolean) → [a] → [a]
let takeLastWhile = useWith(
pipe(takeWhile, reverse), [
identity,
reverse
]
);
takeLastWhile(x => x % 2)(data); // ?
也可以使用 useWith()
進一步將 pred
point-free,由 pipe()
寫法可發現:
reverse()
看似最後執行,但實則pipe(takeWhile, reverse)
才是最後執行 function- 第一個 argument 為 predicate,因為不變,所以為
identity()
- 第二個 argument 為
reverse()
由於第一個 argument 與第二個 argument 並不相關,明顯暗示需使用 useWith()
才能 point-free。
Ramda
import { takeLastWhile } from 'ramda';
let data = [2, 4, 1, 3];
takeLastWhile(x => x % 2)(data); // ?
Ramda 已經提供 takeLastWhile()
,可直接使用。
takeLastWhile()
(a → Boolean) → [a] → [a]
根據自訂條件取得 array 最後幾筆資料
(a -> Boolean)
:自訂條件 predicate
[a]
:data 為 array
[a]
:回傳 array 最後幾筆資料
Point-free
import { takeLastWhile, compose, modulo, __, equals } from 'ramda';
let data = [2, 4, 1, 3];
let pred = compose(
equals(1),
modulo(__, 2)
);
takeLastWhile(pred)(data); // ?
也可將 x => x % 2
進一步 point-free。
- 使用
modulo()
取得餘數,相當於% 2
- 使用
equals()
判斷相等,相當於=== 1
最後使用 compose()
組合所有 function,非常清楚。
Object
import { takeLastWhile } from 'ramda';
let data = [
{ title: 'FP in JavaScript', price: 300 },
{ title: 'RxJS in Action', price: 203 },
{ title: 'Speaking JavaScript', price: 101 }
];
console.dir(takeLastWhile(x => x.price % 2)(data));
takeWhile()
也能用在 object。
Point-free
import { takeLastWhile, compose, prop, modulo, __, equals } from 'ramda';
let data = [
{ title: 'FP in JavaScript', price: 300 },
{ title: 'RxJS in Action', price: 203 },
{ title: 'Speaking JavaScript', price: 101 }
];
let pred = compose(
equals(1),
modulo(__, 2),
prop('price')
);
console.dir(takeLastWhile(pred)(data));
也可將 x => x.price % 2
進一步 point-free。
- 使用
prop()
取得 property 值,相當於x.price
- 使用
modulo()
取得餘數,相當於% 2
- 使用
equals()
判斷相等,相當於=== 1
最後使用 compose()
組合所有 function,非常清楚。
Conclusion
takeLastWhle()
與takeWhile()
用法很類似,但takeWhile()
是取得前幾筆資料,而takeLastWhile()
是取得最後幾筆資料takeLastWhile()
除了用在 array,也能用在 string
Reference
Ramda, takeLastWhile()
Ramda, takeWhile()
Ramda, pipe()
Ramda, reverse()
Ramda, useWith()
Ramda, identity()
Ramda, compose()
Ramda, equals()
Ramda, modulo()
Ramda, prop()