字符串有拼接方法吗?

IT技术 javascript
2021-02-20 14:40:23

Javascriptsplice仅适用于数组。字符串有类似的方法吗?还是应该创建自己的自定义函数?

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

6个回答

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

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);
}

而不是使用拆分后加入(Kumar Harsh 的方法),如下所示:

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

这是一个jsperf,它比较了这两种方法和其他几种方法。(jsperf 已经关闭几个月了。请在评论中提出替代方案。)

尽管上面的代码实现了重现 的一般功能的函数splice,但是针对提问者呈现的情况优化代码(即,不向修改后的字符串添加任何内容)并不会改变各种方法的相对性能。

spliceSlice 和 spliceSplit 在功能上不相等,因为 Array.prototype.splice 接受负索引:jsfiddle.net/sykteho6/5
2021-04-21 14:40:23
@Mzialla 谢谢,我已经添加了代码来处理它。
2021-04-28 14:40:23
创建临时变量并为逐一错误引入位置,更不用说与 split("").splice(...).join("") 相比,人类需要更长时间处理的代码是一种权衡值得考虑。速度问题只是一个问题,如果它是一个问题。
2021-05-06 14:40:23
@WilliamNeely:var StringUtils={'StringSplice':/*func def*/};将是字符串操作的标准,因为您已经说过它是不可变的。
2021-05-15 14:40:23
您可以通过以下方式全局添加: String.prototype.splice = function (index, count, add) { return this.slice(0, index) + (add || "") + this.slice(index + count); } 请记住,它与数组 splice 方法的工作方式并不完全相同,因为字符串是不可变的(一旦创建就无法修改它们)。所以用法如下:var s="ss"; s = s.splice(0,1,"t");
2021-05-20 14:40:23

编辑

这当然不是“拼接”字符串的最佳方式,我已经给出了它作为实现方式的示例,这是有缺陷的,并且从 split()、splice() 和 join() 中非常明显。要获得更好的实现,请参阅Louis 的方法。


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

newStr = str.split(''); // or newStr = [...str];
newStr.splice(2,5);
newStr = newStr.join('');

我意识到没有splice像数组那样的函数,所以你必须将字符串转换为数组。运气不好...

是的,不幸的是,这是正确的。但是您可以通过使用 String.prototype.indexOf 作为获取字符的索引"asdsd".indexOf('s');
2021-05-01 14:40:23
除了使用 str.split,您还可以使用 ES6 扩展语法,如下所示: [...str]
2021-05-02 14:40:23
就我而言,我正在处理动态字符串,因此我需要指定索引而不是字符值。
2021-05-08 14:40:23

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

第二个函数的签名与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');

我知道已经有一个可以接受的答案,但希望这是有用的。

NP。您甚至可以将其抽象为允许,例如,一个可选'method'参数,以便您可以传入 anArray.prototype[method]并将字符串完全视为数组。此外,单独使用这个,您可以将实际过程抽象为另一个函数——如果没有字符串,则返回一个函数,该函数将接受字符串并反转咖喱:mutate()(1, 1, '1')('101'); 您甚至可以使用duckType 参数来消除空调用的咖喱——甚至封装一个方法本身。如果您需要这些东西,您可能需要查看命令模式只是在这里吐痰。
2021-04-23 14:40:23
非常好的方法!
2021-05-21 14:40:23

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

澄清

从 " string.splice" 可能会期望它,就像数组一样:

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

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

在 JavaScript 中,字符串是原始值类型而不是对象 ( spec )。事实上,作为ES5的,他们是只有5值类型之一旁边nullundefinednumberboolean字符串按不是按引用分配,并按原样传递。因此,字符串不仅是不可变的,它们还是一个更改字符串"hello""world"就像决定,从现在起的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);
}

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

    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;
    }

甚至

    index = index % this.length;
    if (index < 0)
        index = this.length + index;

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

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

表现

随着琴弦长度的增加,性能差异会急剧增加。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

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

我想为 Kumar/Cody 和 Louis 方法提供一个更简单的替代方案。在我运行的所有测试中,它的执行速度与 Louis 方法一样快(请参阅基准测试的小提琴测试)。

String.prototype.splice = function(startIndex,length,insertString){
    return this.substring(0,startIndex) + insertString + this.substring(startIndex + length);
};

你可以这样使用它:

var creditCardNumber = "5500000000000004";
var cardSuffix = creditCardNumber.splice(0,12,'****');
console.log(cardSuffix);  // output: ****0004

查看测试结果:https : //jsfiddle.net/0quz9q9m/5/

, otherwise the third argument is not optional. This implementation also doesn't take care of 与其他建议不同,您至少应该做 ` + (insertString || "") + ` 而不是 ` + insertString + startIndex < 0` 很好的用法示例,虽然
2021-05-01 14:40:23