字符串是否有拼接方法?

Pro*_*eek 76 javascript

Javascript splice仅适用于数组.字符串有类似的方法吗?或者我应该创建自己的自定义功能?

substr()substring()方法将只返回提取的字符串,而不是修改原始字符串.我想要做的是从我的字符串中删除一些部分并将更改应用于原始字符串.此外,该方法replace()在我的情况下不起作用,因为我想删除从索引开始并以其他索引结束的部分,就像我可以用该splice()方法做的那样.我尝试将我的字符串转换为数组,但这不是一个简洁的方法.

Lou*_*uis 79

将字符串切片两次更快,如下所示:

function spliceSlice(str, index, count, add) {
  // We cannot pass negative indexes directly to the 2nd slicing operation.
  if (index < 0) {
    index = str.length + index;
    if (index < 0) {
      index = 0;
    }
  }

  return str.slice(0, index) + (add || "") + str.slice(index + count);
}
Run Code Online (Sandbox Code Playgroud)

比使用拆分后跟连接(Kumar Harsh的方法),如下所示:

function spliceSplit(str, index, count, add) {
  var ar = str.split('');
  ar.splice(index, count, add);
  return ar.join('');
}
Run Code Online (Sandbox Code Playgroud)

这是一个比较两者和其他几种方法的jsperf.(jsperf现在已经停止了几个月.请在评论中提出备选方案.)

虽然上面的代码实现了重现其一般功能的函数splice,但优化了提问者提供的案例的代码(即,不对修改后的字符串添加任何内容)并不会改变各种方法的相对性能.

  • 您可以使用以下命令全局添加:```String.prototype.splice = function(index,count,add){return this.slice(0,index)+(add ||"")+ this.slice(index + count ); 只要记住它与数组拼接方法完全不同,因为字符串是不可变的(一旦创建就不能修改它们).所以用法就像:```var s ="ss"; s = s.splice(0,1,"t");``` (3认同)
  • 创建临时变量并引入差一错误的位置,更不用说与 split("").splice(...).join("") 相比人类需要更长的时间来处理的代码是一种权衡值得考虑。速度问题只是一个问题。 (2认同)

kum*_*rsh 14

编辑

这当然不是"拼接"字符串的最佳方式,我已经将此作为实现方式的一个示例,这是一个有缺陷的,并且从split(),splice()和join()中非常明显.有关更好的实现,请参阅Louis的方法.


不,没有这样的东西String.splice,但你可以试试这个:

newStr = str.split(''); // or newStr = [...str];
newStr.splice(2,5);
newStr = newStr.join('');
Run Code Online (Sandbox Code Playgroud)

我意识到spliceArrays中没有函数,所以你必须将字符串转换为数组.好运......

  • 您可以使用ES6扩展语法,而不是使用str.split:`[... str]` (2认同)

Yak*_*ovL 7

似乎有很多困惑,只有 elclanrs 和 raina77ow 的评论才解决,所以让我发布一个澄清的答案。

澄清

从“ string.splice”中,人们可能会期望它,就像数组中的一样:

  • 最多接受 3 个参数:起始位置、长度和(可选)插入(字符串)
  • 返回剪掉的部分
  • 修改原始字符串

问题是,无法满足 3d 要求,因为字符串是不可变的(相关:1 , 2 ),我在这里找到了最专门的评论:

在 JavaScript 中,字符串是原始值类型,而不是对象 ( spec )。事实上,从 ES5 开始,它们是与nullundefinednumber和一起的仅有的 5 种值类型之一boolean字符串是按值分配的,而不是按引用分配的,并按原样传递。因此,字符串不仅仅是不可变的,它们还是一个。将字符串更改"hello""world"is 就像决定从现在开始数字 3 就是数字 4...这没有任何意义。

因此,考虑到这一点,人们可能会期望“ string.splice”事物只会:

  • 最多接受 2 个参数:起始位置、长度(插入没有意义,因为字符串未更改)
  • 返回剪掉的部分

这是substr做什么的;或者,或者,

  • 最多接受 3 个参数:起始位置、长度和(可选)插入(字符串)
  • 返回修改后的字符串(没有剪切部分并有插入)

这是下一节的主题。

解决方案

如果您关心优化,您可能应该使用 Mike 的实现:

String.prototype.splice = function(index, count, add) {
    if (index < 0) {
        index += this.length;
        if (index < 0)
            index = 0;
    }
    return this.slice(0, index) + (add || "") + this.slice(index + count);
}
Run Code Online (Sandbox Code Playgroud)

不过,处理越界索引可能会有所不同。根据您的需求,您可能需要:

    if (index < 0) {
        index += this.length;
        if (index < 0)
            index = 0;
    }
    if (index >= this.length) {
        index -= this.length;
        if (index >= this.length)
            index = this.length - 1;
    }
Run Code Online (Sandbox Code Playgroud)

甚至

    index = index % this.length;
    if (index < 0)
        index = this.length + index;
Run Code Online (Sandbox Code Playgroud)

如果您不关心性能,您可能需要采用 Kumar 的更直接的建议:

String.prototype.splice = function(index, count, add) {
    var chars = this.split('');
    chars.splice(index, count, add);
    return chars.join('');
}
Run Code Online (Sandbox Code Playgroud)

表现

性能差异随着弦的长度而急剧增加。jsperf显示,对于长度为 10 的字符串,后一个解决方案(拆分和连接)比前一个解决方案(使用切片)慢两倍,对于 100 个字母的字符串,它是 x5,对于 1000 个字母的字符串,它是 x50,在 Ops/秒是:

                      10 letters   100 letters   1000 letters
slice implementation    1.25 M       2.00 M         1.91 M
split implementation    0.63 M       0.22 M         0.04 M
Run Code Online (Sandbox Code Playgroud)

请注意,当从 10 个字母移动到 100 个字母时,我更改了第 1 个和第 2d 个参数(仍然令我惊讶的是 100 个字母的测试比 10 个字母的测试运行得更快)。


Cod*_*ody 5

这是一个很好的小咖喱,它提供了更好的可读性(恕我直言):

第二个函数的签名与Array.prototype.splice方法相同.

function mutate(s) {
    return function splice() {
        var a = s.split('');
        Array.prototype.splice.apply(a, arguments);
        return a.join('');
    };
}

mutate('101')(1, 1, '1');
Run Code Online (Sandbox Code Playgroud)

我知道已经有一个公认的答案,但希望这很有用.