JavaScript 字符串中替换多个指定区间字符

const origin = 'abcdefghijklmn';

比如需要替换 index 在 (2,4) 和 (5,6) 这两个区间内的字符,用中括号包上(改变了原字符串的长度)

坐标的替换可以理解为使用 Array.prototype.slice()

期待结果为 ab[cd]e[f]ghijklmn

由于需要替换,所以不会有跨区间的情况。原始字符串也不一定是一串英文,可以是任意的字符串,比如中文或者是一段话。

求问有什么好的办法吗?

阅读 3.8k
3 个回答
const replaceInRanges = f => str => (...ranges) => [...ranges, [] ].reduce(([str_now, idx_now], [l, r]) => [
    str_now + str.slice(idx_now, l) + (r ? f(str.slice(l, r)) : ""), r
], ["", 0])[0]

// => "12[34]5[6]789"
replaceInRanges(s => `[${s}]`)("123456789")([ 2, 4 ], [5, 6])

题主改了题目,那就按索引拆分再组合

function markRange(source, ...ranges) {
    const marks = ["[", "]"];
    const segments = [...ranges.flat(), Infinity]
        .reduce(([segments, start], end, index) => {
            segments.push(source.slice(start, end), marks[index % 2]);
            return [segments, end];
        }, [[], 0])[0];
    segments.pop();

    return segments.join("");
}

const result = markRange(origin, [2, 4], [5, 6]);
console.log(result);

上面是拆成数组,再组合;也可以直接拼接字符串,就是 @ForkKILLET 的思路

function markRange(source, ...ranges) {
    const [result, lastEnd] = ranges.reduce(
        ([result, lastEnd], [begin, end]) => {
            result += source.slice(lastEnd, begin);
            result += `[${source.slice(begin, end)}]`;
            return [result, end];
        },
        ["", 0]
    );
    return result + source.slice(lastEnd);
}

思路是一样的(除处理最后一部分的思路不一样),不知道这个能不能看得明白。


之前的回答,解决将 "123456789"(2,4)(5,6) 处理成 "12[34]5[6]789" 的方法。

第一种方法,正则表达式

const origin = "123456789";
const result = origin.replaceAll(/(?<=2)\d*4|(?<=5)\d*6/g, (m) => {
    return `[${m}]`;
});
console.log(result);
// 12[34]5[6]789

第二种方法,使用更灵活(可自由选择区间,但区间不能有交叉)

function markRange(source, ...ranges) {
    const marks = ["[", "]"];
    return ranges.flat()
        .reduce(
            ([tokens, rest], c, i) => {
                const [left, right] = rest.split(c, 2);
                tokens.push(left, c, marks[i % 2]);
                return [tokens, right];
            },
            [[], source]
        )[0]
        .join("");
}

const result = markRange(origin, [2, 4], [5, 6]);
console.log(result);

我觉得你的问题描述还是很不清晰,所谓的(2,4),(5,6)之间,这个范围到底怎么取的,你给的例子中2没有被包,5也没有被包,感觉上真正的要求是(2,4],(5,6]这范围之间的数字被包?!

如果字符串12346789又应该获得什么样的结果呢?!

建议你多举几个例子,才好说处理方案啊!


根据题主新的题目内容,其实有多种方法可以处理,简单点就是字符串分隔再组合

newStr = oldStr.substring(0,2)+'['+oldStr.substring(2,4)+']'+
        oldStr.substring(4,5)+'['+oldStr.substring(5,6)+']'+
        oldStr.substring(6)
oldStr=newStr
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏