點燈坊

失くすものさえない今が強くなるチャンスよ

使用 dropLastWhile() 根據自訂條件刪除 String 最後幾個 Char

Sam Xiao's Avatar 2019-07-29

dropLast() 只能刪除 String 固定最後幾個 Char,若想自行提供自訂條件 Predicate,就得使用 dropLastWhile()

Version

macOS Mojave 10.14.5
VS Code 1.36.1
Quokka 1.0.238
Ramda 0.26.1

Imperative

let data = 'FP in JavaScript';

// dropLastWhile :: (a -> Boolean) -> String -> String
let dropLastWhile = pred => str => {
  let i = str.length - 1;

  while(i > 0 && pred(str[i]))
    i--;

  return str.slice(0, i + 1);
};

dropLastWhile(x => x !== ' ')(data); // ?

dropLastWhile() 意義為當 predicate 為 true 時從最後刪除 char,直到 false 時停止刪除。

建立 dropLastWhile(),imperative 會先由 length 建立 i,使用 while loop,當 i 大於 0 且 predicate 為 truei 減少 1 ,最後使用 slice() 回傳剩餘 string。

droplastwhile000

Functional

import { pipe, reverse, dropWhile } from 'ramda';

let data = 'FP in JavaScript';

// dropLastWhile :: (a -> Boolean) -> String -> String
let dropLastWhile = pred => str => pipe(
  reverse,
  dropWhile(pred),
  reverse
)(str);


dropLastWhile(x => x !== ' ')(data); // ?

若不知道 Ramda 已經提供 dropLastWhile() 也沒關係,可透過 drop()reverse() 組合出。

  • 使用 reverse() 將 string 反轉
  • 使用 dropWhile() 將 string 前幾個 char 刪除
  • 使用 reverse() 再將 string 反轉

最後使用 pipe() 組合所有 function,非常清楚。

droplastwhile001

Point-free

import { pipe, reverse, dropWhile } from 'ramda';

let data = 'FP in JavaScript';

// dropLastWhile :: (a -> Boolean) -> String -> String
let dropLastWhile = pred => pipe(
  reverse,
  dropWhile(pred),
  reverse
);

dropLastWhile(x => x !== ' ')(data); // ?

dropLastWhile() 最後一個 data argument 也可省略成為 point-free。

droplastwhile002

Ramda

import { dropLastWhile } from 'ramda';

let data = 'FP in JavaScript';

dropLastWhile(x => x !== ' ')(data); // ?

事實上 Ramda 已經內建 dropLastWhile(),可直接使用。

dropLastWhile()
(a -> Boolean) → String → String
根據自訂條件刪除 string 最後幾個 char

(a -> Boolean):自訂條件 predicate

[a]:data 為 string

[a]:回傳刪除 string 最後幾個 char 後的剩餘 string

droplastwhile003

Point-free

import { dropLastWhile, complement, equals } from 'ramda';

let data = 'FP in JavaScript';

let pred = complement(equals)(' ');

dropLastWhile(pred)(data); // ?

也可將 x => x !== ' ' 進一步 point-free。

  • equals()complement() 組合,相當於 !===
  • 將組合後的 function 傳入 ' ',相當於 !=== ' '

droplastwhile004

Conclusion

  • dropWhle()dropLastWhile() 用法很類似,但 dropWhile() 是刪除符合條件前 n 個 char,而 dropLastWhile() 是刪除符合條件最後 n 個 char
  • dropWhile() 除了用在 string,也能用在 array

Reference

Ramda, dropLastWhile()
Ramda, dropWhile()
Ramda, pipe()
Ramda, reverse()
Ramda, complement()
Ramda, equals()