我们在工作中,经常会遇到把字符串切割成数组的情况,官方也为我们提供了 stringObject.split(separator,howmany) 方法,实例:
const str = '开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤'
console.log(str.split(','))// 结果
// ['开心哈哈哈哈', '悲伤哈哈哈', '快乐哈哈哈', '是你', '开始', '开心', '悲伤']
但它只能以 某一个字符 进行分割,并且分割完之后,该字符( split(‘开心’) 里的‘开心’ )会被 的 ‘,’ 替换掉,不能保留原始的 字符串。
现在,我们有这样一个需求,把 ‘开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤’ 这个字符串,按照 [’‘开心’, ‘悲伤’] 这两个字符进行切分,并且得到的数组能够完全保留原始字符串
// 输入
const str = '开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤'// 处理
const result = splitFun(str)// 输出
console.log(result)
['开心', '哈哈哈哈,', '悲伤', '哈哈哈,快乐哈哈哈,是你,开始,', '开心', ',', '悲伤']//最终我们再把 输出的数组 渲染到页面上,能够得到 与原始字符串 完全相同的字符串// react:
(result || []).map(item => <span>{item}</span>)// vue:
<span v-for"item in result" :key="item">{{item}}</span>// 开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤
思路梳理:
1、 实现 字符串分割为数组 有很多方式:split, slice,正则表达式…等等方法,最简单的还是采用 split 。
2、 虽然 split 一次只能以一个字符进行分割,但是我们通过 轮询(for循环)的方式,多执行几次,应该是可以达到效果:当我们 第一次把一个字符串 按照第一个字符 分割成为数组之后,还需要对数组里面的 每一项 按照第二个字符 进行分割, 以此类推 可以实现按照多个字符串进行分割。
3、 split 以某个字符 切割完之后,这个字符就被替换为 ‘,’ 了,要想保留原始字符,必须在每次 split 之后,将这个字符插入进去。
第一步:轮询 分割字符 数组
// 为什么以数组的形式存放 该字符串:当我们 第一次把一个字符串 按照第一个字符 分割成为数组之后,
// 还需要对数组里面的 每一项 按照第二个字符 进行分割,这是一个轮询的过程,
// 所以,一开始我们就以一个数组的形式去存放初始数组。
let array = ['开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤']const labels = ['开心', '悲伤']for(let i = 0; i < labels.length; i++) {// 分割字符串操作const twoArray = splitFunc(array, labels[i])
}
第二步:分割字符
const splitFunc = (array, label) => {// 定义 一个数组 去存放这一轮 最终被分割 好的数组const outArray = []// 循环 需要被分割的 数组字符串for(let i = 0; i < array.length; i++) {// 定义 一个数组 去存放 当前项 最终被分割 好的数组let newArr = []// 把 当前项 的字符串 按照 传进来 字符进行分割const splitArr = array[i].split(label)// 得到分割好的数组后,将被 替换为 ‘,’ 的 label 追加进数组的相应位置// 例如: ‘开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤’, 以 ‘开心’ 分割// 被分割为 ["", "哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,", ",悲伤"]// , 每一项的末尾,就应该应该是 开心 二字,最后一项的末尾除外// 遍历被分割好的数组for(let j = 0; j < splitArr.length; j++) {// 向被分割好的数组里 追加 label 字符newArr.push(splitArr[j])// 数组的末尾无需 追加if (j < splitArr.length -1) {newArr.push(label)}}// 把当前轮得到 的数组 推到 outArray 里去outArray.push(newArr)}// 返回 outArray ,注意 outArray 是一个二维数组return outArray
}
第三步:轮询调用 splitFunc 函数
for(let i = 0; i < labels.length; i++) {// 接收 当前轮 返回的 二维数组const twoArray = splitFunc(array, labels[i])// 将二维数组平铺成为 一维数组const oneArray = twoArray.reduce(function (a, b) { return a.concat(b)} )// 过滤掉一维数组里的空字符串,并把它重新赋值给 array, // 下一轮循环将 切割 上一轮 已经被分割好的 数组array = oneArray.filter(item => item !== "")}// 最终循环结束的 array 就是被彻底分割好的数组
最终代码:
const splitFunc = (array, label) => {const outArray = []for(let i = 0; i < array.length; i++) {let newArr = []const splitArr = array[i].split(label)console.log('splitArr', splitArr)for(let j = 0; j < splitArr.length; j++) {newArr.push(splitArr[j])if (j < splitArr.length -1) {newArr.push(label)}}outArray.push(newArr)}return outArray
}let array = ['开心哈哈哈哈,悲伤哈哈哈,快乐哈哈哈,是你,开始,开心,悲伤']const labels = ['开心', '悲伤']for(let i = 0; i < labels.length; i++) {const twoArray = splitFunc(array, labels[i])const oneArray = twoArray.reduce(function (a, b) { return a.concat(b)} )array = oneArray.filter(item => item !== "")}console.log('array', array)
为什么需要如此麻烦的 将一个字符串 分割完成 之后,在组装渲染到页面上?
主要是为了 这些字符里的 关键字符(也就是 需要被分割的字符),在渲染的时候,能够被我们所控制,为他设置CSS样式,追加点击事件等等,达到动态的效果,如果仅仅是一个字符串被渲染到页面上,这些操作我们将无法控制。
如果以上算法逻辑有不足之处,欢迎大家指出教导👏👏。