JS 中的阵列 trim 方法

JavaScript 中有字串的 trim 方法,但却没有阵列的 trim ,现在就来尝试实作一个阵列的 trim 吧。

本文的範例不考虑型别错误等问题,聚焦于方法本身的说明。

字串的 trim

在实作前,我们先来了解一下 trim 这个方法的功用,在字串的 trim 中,会将前后的空白字元,包括行的结束字符从字串中去除,例如下面这字串:

` helloworld `

string

开头有个空白字元中间有空白及换行字元结尾有换行字元

使用了 trim 回传的结果为:

string-trim

只剩下中间的空白及换行字元

大部分的情况下,由于字串前后的空白及换行字元多半是没有意义且容易造成 bug 产生,例如比对字串是否相等时:

'hi' === 'hi ' // false

这时候 trim 就很有用处:

'hi'.trim() === 'hi '.trim() // true

除了前后都作用的 trim 之外,也有只作用一边的方法:

' ya '.trimStart() // 'ya '' ya '.trimEnd() // ' ya'

特定字元的 trim

前面内建的 trim 很好用,但如果想要删去的是除了空白和换行字元以外的其他字元呢?例如:底线(_)或是小老鼠(@)。

这是就需要自製的方法来达成,首先设计介面:

function trimChar(string, chars) {...}
string: String 型别,原字串chars: String 型别,要删除的字元回传值是 trim 作用过的字串

也可以直接写在 Stringprototype 上: String.prototype.trimChar = function(chars) {...}

接下来实作方法:

function trimChar(string, chars) {    const strArr = string.split('');  // 找到第一个不排除的字元索引  const start = strArr.findIndex(ch => !chars.includes(ch));  if(start === -1) return '';  // 找到最后一个不排除的字元索引  let reverseStart = strArr.slice().reverse().findIndex(ch => !chars.includes(ch));  const end = string.length - reverseStart;  // 去头去尾  return strArr.slice(start, end).join('');}
trimChar('!hello!@world@', '!@'); // "hello!@world"
因为要仰赖阵列处理,先将字串分割为字元阵列使用 findIndex 找到第一个不排除的字元索引如果找不到的话,代表整个字串都是想要排除的字元组成,因此回传空字串将原字串反转找出第一个不排除的字元,此为最后一个不排除的字元的索引由于取得的索引是反转后的,所以需要利用字串长度反转回正确的索引用 slice 删除前后想要排除的字元,并合併后回传

这样 trim 特定字元的方法就建置完成了。

只 trim 开头/结尾特定字元

上面的是前后都 trim 的方法,想想如果只 trim 开头或结尾其一的方法怎么写呢?

function trimCharStart(string, chars) {    const strArr = string.split('');  // 找到第一个不排除的字元索引  const start = strArr.findIndex(ch => !chars.includes(ch));  if(start === -1) return '';  // 直接取长度当作结尾索引  const end = string.length;  // 去头去尾  return strArr.slice(start, end).join('');}function trimCharEnd(string, chars) {    const strArr = string.split('');  // 直接取 0 为开头索引  const start = 0;  // 找到最后一个不排除的字元索引  let reverseStart = strArr.slice().reverse().findIndex(ch => !chars.includes(ch));  const end = string.length - reverseStart;  // 去头去尾  return strArr.slice(start, end).join('');}
trimCharStart('!hello!@world@', '!@'); // "hello!@world@"trimCharEnd('!hello!@world@', '!@'); // "!hello!@world"

只要将开头/结尾的索引设回原本的值就可以了。

阵列中的 trim

看了字串的 trim 实作后,对于阵列的 trim 有没有一点概念了呢?接着就来想一下改怎么处理阵列的部分吧。

阵列 trim 的定义

首先先来定义阵列 trim 介面:

function arrayTrim(array, exclude) {...}
array: any[] 型别,原阵列exclude: element => boolean 型别,要排除的元素传回 true 的回呼函数回传值是 trim 作用过的阵列

同字串 trim 也可以写在 Array.prototype 上。

可以先试着用上面字串的思维想想要怎么实作 arrayTrim

实作 arrayTrim

function arrayTrim(array, exclude) {  // 找到第一个不排除的字元索引  const start = array.findIndex(ch => !exclude(ch));  if(start === -1) return '';  // 找到最后一个不排除的字元索引  let reverseStart = array.slice().reverse().findIndex(ch => !exclude(ch));  const end = array.length - reverseStart;  // 去头去尾  return array.slice(start, end);}

可以发现跟字串的方法大同小异,这是因为在上面讲解字串 trim 时刻意使用阵列的思路来说明,要不然字串可以使用正规表达式写出更简洁的方法,详细可以参考 StackOverflow 上的解答。

// ex1arrayTrim(['!', 'hello', '!', '@', 'world', '@'], element => ['!', '@'].includes(element));// ["hello", "!", "@", "world"]// ex2arrayTrim([[0, '@'], [1, 'hello'], [2, '!'], [3, '@'], [4, 'world'], [5, '@']], element => ['!', '@'].includes(element[1]));// [[1, 'hello'], [2, '!'], [3, '@'], [4, 'world']]

阵列的第二个参数会需要是回呼函数,因为阵列中可能会是複杂结构,像是第二个例子一样。

trim 阵列的开头/结尾的方法就交给各位想想喽~

结论

会需要这个方法是由于最近处理到时间流的资料,他的资料会像下面这样:

const datapoints = [  [622,1450754160000],  [587,1450754220000],  [622,1450754280000],  [123,1450754340000],  [622,1450754400000],  [851,1450754460000]];

待在某个时间点的资料有可能是 null

const datapoints = [  [null,1450754160000],  [587,1450754220000],  [null,1450754280000],  [123,1450754340000],  [622,1450754400000],  [null,1450754460000]];

绘图时前后的资讯是不需要的,因为那个时间点本来就还没有资料或是已经没有资料了,但中间的资料如果是 null 的话就需要将图上的那个时间画为 0 值,否则前后的资料会相连使人误以为这是连续的数值。

参考资料

MDN: String.prototype.trim()MDN: Array.prototype.findIndex()Sonya Moisset: Reverse a String in JavaScriptstackoverflow: Trim specific character from a stringLodash: trim

同步发表于 Limitless Ping


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章