好 pipe 不用嗎?(. ❛ ᴗ ❛.),讓程式碼更簡潔彈性吧!

更新於 發佈於 閱讀時間約 8 分鐘
raw-image
鱈魚的魚缸搬家了!新家文章有重新修訂,歡迎來新家看看喔。(´▽`ʃ♡ƪ)

甚麼是 pipe

顧名思是就是水管,但是不會像瑪利歐由人來鑽,而是讓資料通過。

pipe 是一種函數式程式設計中的概念,用來表示一條資料處理的管道。

可以將多個 function 組合在一起,資料會依序經過每個 function 進行處理。

這種方法使程式碼更加清晰、模組化,並且易於維護。

個人覺得和以往指令式的寫法最大差別在於關注點不同。

怎麼說呢?讓我們看看以下兩種等效的程式。

例 1:

const data = [1, 2, 3];
const filteredData = data.filter(value => value > 1);
const result = filteredData.join('-');

例 2:

const result = pipe(
[1, 2, 3],
filter(value => value > 1),
join('-'),
);
我知道你很想問例 1 明明可以一行解決。
先別計較那麼多,只是簡單範例啦。( •̀ ω •́ )✧


可以注意到例 1 的專注點在「結果」,而例 2 的寫法專注點在「過程」,了解差異後學習轉換上就會相對容易了。(應該啦 ¯\( ͡° ͜ʖ ͡°)/¯)

ramda、remeda?

這兩個都是基於 FP 概念設計的優秀套件,其實選一個喜歡的都行。

如果問我到底要用哪一個?實務上我 2 個都用。ヽ(✿゚ ▽゚)ノ

不過主要使用 remeda,remeda 缺少的 function 從 ramda 補。

為甚麼主要用 remeda 呢?因為 remeda 可以完美配合 TypeScript,而且同時支援 data-first 與 data-last 的寫法,兩個範例如下:

  • data-first:
const data = {
name: 'cod',
age: '18',
}

const result = pick(data, ['name']);
  • data-last:
const data = {
name: 'cod',
age: '18',
}

const pickName = pick(['name']);
const result = pickName(data);

個人覺得使用上更為直覺。

此外 remeda 還有其他特性,詳細說明就不再此贅述,可以參考以下文檔。

Remeda

所以 pipe 有甚麼好處?

個人覺得最大的好處是不用一直想變數名稱 XD,而且 function 方便抽換,整體來說增加了程式的彈性。

讓我們看看以下例子。

假設我們有多個 IoT 設備回傳資料,網頁需要彙整並顯示內容,資料為:

interface Datum {
deviceId: string;
type: string;
temperature: number;
humidity: number;
otherSensorData: {
type: string;
value: number;
}[];
}

const data: Datum[] = [
{
deviceId: 'device_1',
type: 'A',
temperature: 24.5,
humidity: 50.0,
otherSensorData: [
{ type: 'A', value: 10 },
{ type: 'A', value: 20 }
]
},
{
deviceId: 'device_2',
type: 'B',
temperature: 22.3,
humidity: 45.5,
otherSensorData: [
{ type: 'B', value: 15 },
{ type: 'C', value: 25 }
]
}
]

以下讓我們來實際撰寫程式。

列出所有設備 ID 並用頓號分隔

熟悉 JS 的人一定可以很快寫出以下程式:

const result01 = data
.map(({ deviceId }) => deviceId)
.join('、');

用 pipe 寫則會像這樣:

const result02 = pipe(
data,
map(prop('deviceId')),
join('、')
);

看起來好像沒比較好捏?但是用 remeda 可以更簡單抽離與複用:

const getDeviceIdListString = createPipe(
map<Datum, string>(prop('deviceId')),
join('、')
);

也方便加入新的處理邏輯:

import { trim } from 'ramda';

const getDeviceIdListString = createPipe(
/** 將每個 deviceId 去除頭尾空白 */
map<Datum, string>(
createPipe(prop('deviceId'), trim),
),
join('、'),
);

邏輯越複雜效果會越明顯,來看看其他例子。

將設備依照 type 分類

const groupByType = pipe(
data,
groupBy(prop('type')),
values,
);

取得平均溫度與平均濕度

const meanData = {
temperature: pipe(data, meanBy(prop('temperature'))),
humidity: pipe(data, meanBy(prop('humidity'))),
};

取得 otherSensorData type 種類清單

const typeList = pipe(
data,
/** 將所有 otherSensorData 攤平、組成新矩陣 */
flatMap(prop("otherSensorData")),
/** 依照 type 數值去除重複項目 */
uniqBy(prop("type")),
/** 取出 type 數值產生新矩陣 */
map(prop("type"))
);

取得所有溫溼度不在舒適範圍內的設備

function isComfortableTemperature(value: number) {
return value >= 22 && value <= 28;
}
function isComfortableHumidity(value: number) {
return value >= 40 && value <= 60;
}

const isComfortable = createPipe(
allPass<Datum>([
createPipe(prop('temperature'), isComfortableTemperature),
createPipe(prop('humidity'), isComfortableHumidity),
])
)

const uncomfortableList = pipe(data, reject(isComfortable))

/**
* 因為只有一個參數,所以也可以用 data-first 的方式寫
* const result = reject(data, isComfortable);
*/

從以上例子來看,其實就算沒有註解,從 function 的名稱我們看得出來此程式在做甚麼。

這樣可讀性是不是提升了許多呢?( •̀ ω •́ )✧


如果錯誤或更好的做法,歡迎大家多多指教。(´▽`)



留言
avatar-img
留言分享你的想法!
avatar-img
鱈魚的魚缸
17會員
14內容數
各種鱈魚滾鍵盤的雜紀
鱈魚的魚缸的其他內容
2024/07/16
一般在使用 TypeScript 的時候,大家都有遇過定義列舉資料的情境吧。 不過不管是 enum 和 literal 的方式其實都有些小缺點,以下推薦一個個人認為體驗更好的方式。
Thumbnail
2024/07/16
一般在使用 TypeScript 的時候,大家都有遇過定義列舉資料的情境吧。 不過不管是 enum 和 literal 的方式其實都有些小缺點,以下推薦一個個人認為體驗更好的方式。
Thumbnail
2024/06/28
ts-rest 可以實現從服務器到客戶端的全型別安全,可以有效降低前後端溝通血流成河的機率。(´,,•ω•,,)
Thumbnail
2024/06/28
ts-rest 可以實現從服務器到客戶端的全型別安全,可以有效降低前後端溝通血流成河的機率。(´,,•ω•,,)
Thumbnail
看更多
你可能也想看
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
當你邊吃粽子邊看龍舟競賽直播的時候,可能會順道悼念一下2300多年前投江的屈原。但你知道端午節及其活動原先都與屈原毫無關係嗎?這是怎麼回事呢? 本文深入探討端午節設立初衷、粽子、龍舟競渡與屈原自沉四者。看完這篇文章,你就會對端午、粽子、龍舟和屈原的四角關係有新的認識喔。那就讓我們一起解開謎團吧!
Thumbnail
當你邊吃粽子邊看龍舟競賽直播的時候,可能會順道悼念一下2300多年前投江的屈原。但你知道端午節及其活動原先都與屈原毫無關係嗎?這是怎麼回事呢? 本文深入探討端午節設立初衷、粽子、龍舟競渡與屈原自沉四者。看完這篇文章,你就會對端午、粽子、龍舟和屈原的四角關係有新的認識喔。那就讓我們一起解開謎團吧!
Thumbnail
  除了上篇提到的 Data Wrangler 外,SageMaker 還有許多配套的功能,其中有個叫做 Pipelines 的東西,說是可以用來構建、 管理及自動化深度學習流程,能夠節省人工操作,有那麼神?這次就來試試 Pipelines 能夠為我們帶來什麼體驗。
Thumbnail
  除了上篇提到的 Data Wrangler 外,SageMaker 還有許多配套的功能,其中有個叫做 Pipelines 的東西,說是可以用來構建、 管理及自動化深度學習流程,能夠節省人工操作,有那麼神?這次就來試試 Pipelines 能夠為我們帶來什麼體驗。
Thumbnail
Lazy evaluation 的效益必須是在 pipe 的組合上有最佳化過的,若組合的不好反而更糟糕,且在 I/O 上幫助似乎也不大。parallel stream 要能發揮效果必須看資料的來源類型,不過要注意的是 parallel stream 也會使記憶體的使用量增加,使用上也要小心。
Thumbnail
Lazy evaluation 的效益必須是在 pipe 的組合上有最佳化過的,若組合的不好反而更糟糕,且在 I/O 上幫助似乎也不大。parallel stream 要能發揮效果必須看資料的來源類型,不過要注意的是 parallel stream 也會使記憶體的使用量增加,使用上也要小心。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
老實說,看到 Java Sream API 讓我感到相當親切,這應該跟我研究所多年的研究題目是 visual dataflow language 有關,Java Stream API 把迴圈給內化了,每個 operation 的重點是要做什麼,大大提高了程式的抽象化程度和可讀性。
Thumbnail
老實說,看到 Java Sream API 讓我感到相當親切,這應該跟我研究所多年的研究題目是 visual dataflow language 有關,Java Stream API 把迴圈給內化了,每個 operation 的重點是要做什麼,大大提高了程式的抽象化程度和可讀性。
Thumbnail
pipe 代表函數式程式設計中的概念,利用多個功能結合在一起,資料依序通過每個功能進行處理。文章中介紹了 pipe 的優點、兩個等效的程式碼比較以及 remeda 套件的使用。詳細介紹了使用 pipe 的好處,並提供了多個相關的例子,展示了 pipe 可讀性的提升。
Thumbnail
pipe 代表函數式程式設計中的概念,利用多個功能結合在一起,資料依序通過每個功能進行處理。文章中介紹了 pipe 的優點、兩個等效的程式碼比較以及 remeda 套件的使用。詳細介紹了使用 pipe 的好處,並提供了多個相關的例子,展示了 pipe 可讀性的提升。
Thumbnail
如果我只是想要重複做一些很簡單的運算,還有沒有更簡潔的方式,那就是Lambda匿名函式。 本文將介紹 : Lambda匿名函式的用法,也比較跟自定函式的差異之處。 結合map,filter,sorted函式做應用介紹
Thumbnail
如果我只是想要重複做一些很簡單的運算,還有沒有更簡潔的方式,那就是Lambda匿名函式。 本文將介紹 : Lambda匿名函式的用法,也比較跟自定函式的差異之處。 結合map,filter,sorted函式做應用介紹
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
👨‍💻簡介 在 Go 語言中,函數(Function)是一個強大且重要的概念,就像食譜一樣,告訴你應該如何處理食材,最後得到一道美味的料理。經過哪些程序讓程式更有組織性和可讀性。函數可幫助你將程式碼區塊組織成可重複使用的元件,進而執行特定的任務。
Thumbnail
👨‍💻簡介 在 Go 語言中,函數(Function)是一個強大且重要的概念,就像食譜一樣,告訴你應該如何處理食材,最後得到一道美味的料理。經過哪些程序讓程式更有組織性和可讀性。函數可幫助你將程式碼區塊組織成可重複使用的元件,進而執行特定的任務。
Thumbnail
方法鏈接和流暢接口在許多現代編程語言和框架中都有使用。這兩個概念有時互相重疊,因為流暢接口通常使用方法鏈接來實現。使用這些技巧可以提高程式碼的可讀性和維護性,使得編碼更符合人類語言的結構。這對於在專案中協同工作的團隊尤為重要,因為它可以讓每個人更容易理解和使用代碼。
Thumbnail
方法鏈接和流暢接口在許多現代編程語言和框架中都有使用。這兩個概念有時互相重疊,因為流暢接口通常使用方法鏈接來實現。使用這些技巧可以提高程式碼的可讀性和維護性,使得編碼更符合人類語言的結構。這對於在專案中協同工作的團隊尤為重要,因為它可以讓每個人更容易理解和使用代碼。
Thumbnail
C# 介面 ( C# Interface ) – (C#教學) – 介面就是類別的接口, 就好像在電插一樣, 不同的電器有同一類與電力的接口. 要編程就像一個布局, 當引用一個class時, 會引用不同的method, property. 如果method的class可以轉換, 就大大簡化了編程.
Thumbnail
C# 介面 ( C# Interface ) – (C#教學) – 介面就是類別的接口, 就好像在電插一樣, 不同的電器有同一類與電力的接口. 要編程就像一個布局, 當引用一個class時, 會引用不同的method, property. 如果method的class可以轉換, 就大大簡化了編程.
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News