字符串有拼接方法吗?


87

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

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


str.split可能是您正在寻找的功能:google.com/#q=javascript+string+split
Anderson Green

1
这有什么错str = str.slice()
elclanrs

1
看起来像XY问题,您到底要做什么?字符串不是通过引用传递的,这与数组和对象不同,因此您不对字符串进行突变,创建新的字符串或将新的字符串重新分配给旧的字符串。
elclanrs


6
return string.slice(0, startToSplice) + string.slice(endToSplice);,不?
raina77ow 2013年

Answers:


88

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

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,但针对请求者提出的案例优化代码(即,不向修改后的字符串添加任何内容)不会改变各种方法的相对性能。


3
您可以通过以下方式全局添加: 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");
William Neely

@WilliamNeely:var StringUtils={'StringSplice':/*func def*/};因为您已经说过它是不可变的,所以它将成为字符串操作的标准。
Polywhirl先生2014年

由于Array.prototype.splice接受负索引:jsfiddle.net/sykteho6/5,因此spliceSlice和spliceSplit在功能上不相等。
马丁·

1
@Mzialla谢谢,我添加了代码来处理它。
路易

创建临时变量并引入一个错误的地方,更不用说与split(“”)。splice(...)。join(“”)相对,人类需要花费更长的时间处理的代码值得考虑。速度问题只是一个问题。
Ben Fletcher

15

编辑

当然,这不是“拼接”字符串的最佳方法,我已经给出了如何实现的示例,这是有缺陷的,从split(),splice()和join()可以很明显地看出来。有关更好的实现,请参见Louis的方法。


不,不存在String.splice,但是您可以尝试以下操作:

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

我意识到没有spliceArrays中的函数,因此您必须将字符串转换为数组。运气不好...


就我而言,我正在处理动态字符串,因此我需要指定索引而不是字符值。
ProllyGeek 2013年

是的,很不幸,这是正确的。但是您可以使用String.prototype.indexOf作为"asdsd".indexOf('s');
kumarharsh,2013年

3
您可以像这样使用ES6扩展语法来代替使用str.split:[...str]
robbie

5

这是一个不错的小咖喱,具有更好的可读性(IMHO):

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

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


1
Np。您甚至可以将其抽象化以允许使用例如可选'method'参数,以便您可以传入Array.prototype[method]和完全像对待数组一样对待字符串。此外,与独此一家,你可以抽象的实际过程到另一个功能-如果没有字符串,返回,将采取字符串和反向咖喱功能:mutate()(1, 1, '1')('101'); 您甚至可以使用duckType参数来消除空调用的咖喱-甚至封装方法本身。如果您需要这些东西,则可能需要查看“命令模式”。只是在这里吐痰。
科迪

3

我想为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` 。使用的一个很好的例子
YakovL

3

似乎只有在Elclanrs和Raina77ow的评论中才解决了很多困惑,所以让我发表一个明确的答案。

澄清度

从“ string.splice”开始,人们可能会期望它像数组中的那个:

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

问题是,在3D的要求不能得到满足,因为字符串是不可变的(相关:12),我发现最敬业的评论在这里

在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个字母的测试要快)。



1

因此,无论在String原型中添加splice方法都不能对规范透明工作。

让我们做一些扩展:

String.prototype.splice = function(...a){
    for(var r = '', p = 0, i = 1; i < a.length; i+=3)
        r+= this.slice(p, p=a[i-1]) + (a[i+1]||'') + this.slice(p+a[i], p=a[i+2]||this.length);
    return r;
}
  • 每3个args组以拼接样式“插入”。
  • 特殊的是,如果有一个以上的3个参数组,则每个切割的结束将是下一个开始。
    • '0123456789'.splice(4,1,'fourth',8,1,'eighth'); //返回'0123fourth567eighth9'
  • 您可以删除或归零每个组中的最后一个arg(被视为“无可插入”)
    • '0123456789'.splice(-4,2); //返回“ 0123459”
  • 您可以删除除最后一个组中的第一个参数以外的所有内容(将其视为“在第一个参数位置之后全部剪切”)
    • '0123456789'.splice(0,2,null,3,1,null,5,2,'/',8); //返回“ 24/7”
  • 如果您通过多个,则必须自己检查从左到右顺序的位置!
  • 而且,如果您不希望,请不要这样使用它:
    • '0123456789'.splice(4,-3,'什么?'); //返回“ 0123what?123456789”

0

Louis的方法作为String原型函数:

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

例:

 > "Held!".splice(3,0,"lo Worl")
 < "Hello World!"

0

当add值为0或其他伪造的值时,Louis的spliceSlice方法失败,这是一个解决方法:

function spliceSlice(str, index, count, add) {
  if (index < 0) {
    index = str.length + index;
    if (index < 0) {
      index = 0;
    }
  }
  const hasAdd = typeof add !== 'undefined';
  return str.slice(0, index) + (hasAdd ? add : '') + str.slice(index + count);
}

0

我使用此代码解决了我的问题,在某种程度上替代了缺少的接头。

let str = "I need to remove a character from this";
let pos = str.indexOf("character")

if(pos>-1){
  let result = str.slice(0, pos-2) + str.slice(pos, str.length);
  console.log(result) //I need to remove character from this 
}

我需要删除某个单词之前/之后的字符,在将字符串拆分为两个位置之后,通过使用偏移量灵活地删除字符来重新组合 pos

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.