JavaScript 中有字串的 trim
方法,但卻沒有陣列的 trim
,現在就來嘗試實作一個陣列的 trim
吧。
本文的範例不考慮型別錯誤等問題,聚焦於方法本身的說明。
字串的 trim
在實作前,我們先來了解一下 trim
這個方法的功用,在字串的 trim
中,會將前後的空白字元,包括行的結束字符從字串中去除,例如下面這字串:
1 | ` hello |
- 開頭有個空白字元
- 中間有空白及換行字元
- 結尾有換行字元
使用了 trim
回傳的結果為:
- 只剩下中間的空白及換行字元
大部分的情況下,由於字串前後的空白及換行字元多半是沒有意義且容易造成 bug 產生,例如比對字串是否相等時:
1 | 'hi' === 'hi ' // false |
這時候 trim
就很有用處:
1 | 'hi'.trim() === 'hi '.trim() // true |
除了前後都作用的 trim
之外,也有只作用一邊的方法:
1 | ' ya '.trimStart() // 'ya ' |
特定字元的 trim
前面內建的 trim
很好用,但如果想要刪去的是除了空白和換行字元以外的其他字元呢?例如:底線(_
)或是小老鼠(@
)。
這是就需要自製的方法來達成,首先設計介面:
1 | function trimChar(string, chars) {...} |
string
:String
型別,原字串chars
:String
型別,要刪除的字元- 回傳值是
trim
作用過的字串
也可以直接寫在
String
的prototype
上:String.prototype.trimChar = function(chars) {...}
。
接下來實作方法:
1 | function trimChar(string, chars) { |
1 | trimChar('!hello!@world@', '!@'); // "hello!@world" |
- 因為要仰賴陣列處理,先將字串分割為字元陣列
- 使用
findIndex
找到第一個不排除的字元索引 - 如果找不到的話,代表整個字串都是想要排除的字元組成,因此回傳空字串
- 將原字串反轉找出第一個不排除的字元,此為最後一個不排除的字元的索引
- 由於取得的索引是反轉後的,所以需要利用字串長度反轉回正確的索引
- 用
slice
刪除前後想要排除的字元,並合併後回傳
這樣 trim
特定字元的方法就建置完成了。
只 trim 開頭/結尾特定字元
上面的是前後都 trim
的方法,想想如果只 trim
開頭或結尾其一的方法怎麼寫呢?
1 | function trimCharStart(string, chars) { |
1 | trimCharStart('!hello!@world@', '!@'); // "hello!@world@" |
只要將開頭/結尾的索引設回原本的值就可以了。
陣列中的 trim
看了字串的 trim
實作後,對於陣列的 trim
有沒有一點概念了呢?接著就來想一下改怎麼處理陣列的部分吧。
陣列 trim 的定義
首先先來定義陣列 trim
介面:
1 | function arrayTrim(array, exclude) {...} |
array
:any[]
型別,原陣列exclude
:element => boolean
型別,要排除的元素傳回true
的回呼函數- 回傳值是
trim
作用過的陣列
同字串
trim
也可以寫在Array.prototype
上。
可以先試著用上面字串的思維想想要怎麼實作 arrayTrim
。
實作 arrayTrim
1 | function arrayTrim(array, exclude) { |
可以發現跟字串的方法大同小異,這是因為在上面講解字串 trim
時刻意使用陣列的思路來說明,要不然字串可以使用正規表達式寫出更簡潔的方法,詳細可以參考 StackOverflow 上的解答。
1 | // ex1 |
陣列的第二個參數會需要是回呼函數,因為陣列中可能會是複雜結構,像是第二個例子一樣。
只
trim
陣列的開頭/結尾的方法就交給各位想想嘍~
結論
會需要這個方法是由於最近處理到時間流的資料,他的資料會像下面這樣:
1 | const datapoints = [ |
待在某個時間點的資料有可能是 null
:
1 |
|
繪圖時前後的資訊是不需要的,因為那個時間點本來就還沒有資料或是已經沒有資料了,但中間的資料如果是 null
的話就需要將圖上的那個時間畫為 0 值,否則前後的資料會相連使人誤以為這是連續的數值。