我有一个索引范围数组和一个字符串:
const ranges = [[2,5], [11, 14]]
const str = 'brave new world'
我正试图写一个函数来插入和包装这些范围内的字符。
const magic = (str, ranges, before='<bold>', after='</bold>') => {
// magic here
return 'br<bold>ave</bold> new w<bold>orl</bold>d'
}
假设您的范围按照需要应用的顺序排列,那么:
- 遍历范围
- 将字符串前面的部分添加到结果中。
- 将中间部分包裹在
before
和after
中 - 记住最后处理的索引是哪个,然后重复2 -4。有许多范围。
- 将最后一个范围后的字符串的其余部分添加到结果中。
const magic = (str, ranges, before='<bold>', after='</bold>') => {
let result = "";
let lastIndex = 0;
for(const [start, end] of ranges) {
result += str.slice(lastIndex, start);
const wrap = str.slice(start, end);
result += before + wrap + after;
lastIndex = end;
}
result += str.slice(lastIndex);
return result;
}
const ranges = [[2,5], [11, 14]]
const str = 'brave new world'
console.log(magic(str, ranges));
很容易编写一个针对单个范围的函数。编写该函数,然后使用reduce
对每个范围重复执行该函数。在这种情况下,您需要确保先执行结束范围,这样它就不会改变先前范围的偏移量。
如果您确保以相反的顺序遍历范围(必要时对数组进行排序,或者如果它们已经排序,则使用reduceRight
),则可以这样简单:
// Wraps one range
function wrap(str, [i, j]) {
const beg = str.substring(0, i),
mid = str.substring(i, j),
end = str.substring(j);
return `${beg}<b>${mid}</b>${end}`;
}
[[2, 5], [11, 14]].reduceRight(wrap, 'brave new world')
所以我会这样写魔法:
function magic(str, ranges, b='<bold>', a='</bold>') {
const wrap = (str, [i, j]) => str.substring(0, i) + b +
str.substring(i, j) + a + str.substring(j);
return ranges.sort(([i], [j]) => j - i).reduce(wrap, str);
}