前段时间遇到一个需求,最后最后一个步骤是进行字符串的拼接。
1、需求
首先选择字符串片段:通过鼠标拖拽选取字符串中的字符,同时记录每一次拖拽选取的内容相对整个字符串是从第几个字符到第几个字符。
- 第一步,选取需要精确处理的,选取次数不限制。
- 第二步,选取需要普通处理的,选取次数不限制。
- 每一次的字符选取都能得到开始位置和结束位置。
拼接规则:
- 对于需要精确处理的,在拼接字符串时要在开始位置插入
****
,同时在结束位置插入****
。 - 对于需要普通处理的,在拼接字符串时要在开始位置插入
####
,同时在结束位置插入####
。 - 若是需要精确处理和需要普通处理的开始位置相同,则在开始位置插入
####****
,若是需要精确处理和需要普通处理的结束位置相同,则在结束位置插入****####
2、解题思路
1、每一次的字符选取都能得到起始位置和结束位置。分别将精确处理和普通处理将每一次选取得到的位置数据都保存在一个数组中。大致格式如下
const exact = [{ start: 0, end: 4 }, { start: 5, end: 7 }, { start: 8, end: 12 }]
const normal = [{ start: 0, end: 3 }, { start: 5, end: 6 }, { start: 7, end: 12 }]
2、可以知道,总是在开始位置之前和结束位置之后插入,同时精确和普通分别插入的字符是*
和#
。那么,可以将这些信息也添加进来。得到下面的结果。
const exactS = [{
index: 0,
position: 'before',
flag: '****'
},
{
index: 5,
position: 'before',
flag: '****'
},
{
index: 8,
position: 'before',
flag: '****'
}]
const exactE = [{
index: 4,
position: 'after',
flag: '****'
},
{
index: 7,
position: 'after',
flag: '****'
},
{
index: 12,
position: 'after',
flag: '****'
}
];
const normalS = [
{
index: 0,
position: 'before',
flag: '####'
},
{
index: 5,
position: 'before',
flag: '####'
}, {
index: 7,
position: 'before',
flag: '####'
}
];
const normalE = [
{
index: 3,
position: 'after',
flag: '####'
}, {
index: 6,
position: 'after',
flag: '####'
}, {
index: 12,
position: 'after',
flag: '####'
}
]
3、将上一步得到的4个数组合并为一个并根据index的值从小到大排序。得到结果如下:
const result = exactS.concat(exactE, normalS, normalE).sort(function (a, b) {
return a.index - b.index
});
result=[
{ index: 0, position: "before", flag: "****" },
{ index: 0, position: "before", flag: "####" },
{ index: 3, position: "after", flag: "####" },
{ index: 4, position: "after", flag: "****" },
{ index: 5, position: "before", flag: "****" },
{ index: 5, position: "before", flag: "####" },
{ index: 6, position: "after", flag: "####" },
{ index: 7, position: "after", flag: "****" },
{ index: 7, position: "before", flag: "####" },
{ index: 8, position: "before", flag: "****" },
{ index: 12, position: "after", flag: "****" },
{ index: 12, position: "after", flag: "####" }
]
4、遍历上一步得到的数组,同时进行字符串的拼接。
- 数组项中,
position
表示是在哪个位置(前/后)插入字符,flag
表示插入哪种字符,index
表示第几个字符 -
{ index: 12, position: "after", flag: "****" }
这样一个数组项表示:在字符串的第12个字符后面插入****
- 遍历数组,根据index的值进行查找,是否还有与index的值相同的数组项
- 如果没有:根据
flag
和position
在相应位置插入指定的字符。 - 如果有:假设两项都是在index之前插入,一个插入****一个插入####,根据提到的插入规则。最终需要在第index个字符前插入
####****
; 都是在第index之后插入,那么最终需要在第index个字符后插入****####
- 至此,所有与相同的index的值相等数组的项已经处理过了,于是处理接着处理后面的数组项。循环执行步骤4到步骤6,直到数组遍历结束。
3、实现代码
大致的字符串拼接实现过程如下:
function stringConcat() {
let initialString = container.textContent;
let hong = '',
holistic = [];
colorPosition.concat(fontsizePosition).forEach((item) => {
holistic.push(
{ index: item.start, position: 'before', tag: item.tag },
{ index: item.end - 1, position: 'after', tag: item.tag }
);
});
holistic = holistic.sort((x, y) => {
return x.index - y.index;
});
holistic.forEach((item, i) => {
const { index } = item;
let arr = findEqualIndex(holistic, index, i);
const currentCode = initialString[index] ? initialString[index] : '';
let preCode;
if (i === 0) {
preCode = initialString.substring(0, index);
} else {
preCode = initialString.substring(holistic[i - 1].index + 1, index);
}
// 找到相同的index
if (arr.length > 0) {
arr = arr.concat([holistic[i]]);
const { beforestr, afterstr } = processSameIndex(arr);
if (i < holistic.length - 1) {
hong += preCode + beforestr + currentCode + afterstr;
} else {
hong +=
preCode +
beforestr +
currentCode +
afterstr +
initialString.substr(index);
}
i = i + arr.length - 1;
} else {
// 找不到相同index,
if (i < holistic.length - 1) {
if (holistic[i].position === 'before') {
hong += preCode + holistic[i].tag + currentCode;
} else {
hong += preCode + currentCode + holistic[i].tag;
}
} else {
if (holistic[i].position === 'before') {
hong +=
preCode +
holistic[i].tag +
initialString.substr(index + 1);
} else {
hong +=
preCode +
currentCode +
holistic[i].tag +
initialString.substr(index + 1);
}
}
}
});
console.log(hong);
}
// 查找相同的index
function findEqualIndex(holistic, index, ind) {
let arr = [];
for (let i = ind + 1; i < holistic.length; i++) {
if (holistic[i].index !== index) {
break;
}
if (holistic[i].index === index) {
arr.push(holistic[i]);
}
}
return arr;
}
// 当index相同时,怎么处理
function processSameIndex(arr) {
let beforestr = '',
afterstr = '',
beforearr = [],
afterarr = [];
for (let item of arr) {
if (item.position === 'before') {
beforearr.push(item);
} else {
afterarr.push(item);
}
}
if (beforearr.length === 0) {
beforestr = '';
} else if (beforearr.length === 1) {
beforestr = beforearr[0].tag;
} else {
let equal = true; // index相同且都在index前插入,插入的符号是否相同
for (let j = 1; j < beforearr.length; j++) {
if (beforearr[j - 1].tag !== beforearr[j].tag) {
equal = false;
beforestr = '####****';
break;
}
}
if (equal) {
beforestr = beforearr[0].tag;
}
}
if (afterarr.length === 0) {
afterstr = '';
} else if (afterarr.length === 1) {
afterstr = afterarr[0].tag;
} else {
let equal = true;
for (let j = 1; j < afterarr.length; j++) {
if (afterarr[j - 1].tag !== afterarr[j].tag) {
equal = false;
afterstr = '****####';
break;
}
}
if (equal) {
afterstr = afterarr[0].tag;
}
}
return { beforestr, afterstr };
}