Is there a splice method for strings?

前端 未结 10 2353
你的背包
你的背包 2020-11-30 23:32

The Javascript splice only works with arrays. Is there similar method for strings? Or should I create my own custom function?

The substr(),

相关标签:
10条回答
  • 2020-11-30 23:45

    There seem to be a lot of confusion which was addressed only in comments by elclanrs and raina77ow, so let me post a clarifying answer.

    Clarification

    From "string.splice" one may expect that it, like the one for arrays:

    • accepts up to 3 arguments: start position, length and (optionally) insertion (string)
    • returns the cut out part
    • modifies the original string

    The problem is, the 3d requirement can not be fulfilled because strings are immutable (related: 1, 2), I've found the most dedicated comment here:

    In JavaScript strings are primitive value types and not objects (spec). In fact, as of ES5, they're one of the only 5 value types alongside null, undefined, number and boolean. Strings are assigned by value and not by reference and are passed as such. Thus, strings are not just immutable, they are a value. Changing the string "hello" to be "world" is like deciding that from now on the number 3 is the number 4... it makes no sense.

    So, with that in account, one may expect the "string.splice" thing to only:

    • accepts up to 2 arguments: start position, length (insertion makes no sense since the string is not changed)
    • returns the cut out part

    which is what substr does; or, alternatively,

    • accepts up to 3 arguments: start position, length and (optionally) insertion (string)
    • returns the modified string (without the cut part and with insertion)

    which is the subject of the next section.

    Solutions

    If you care about optimizing, you should probably use the Mike's implementation:

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

    Treating the out-of-boundaries index may vary, though. Depending on your needs, you may want:

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

    or even

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

    If you don't care about performance, you may want to adapt Kumar's suggestion which is more straight-forward:

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

    Performance

    The difference in performances increases drastically with the length of the string. jsperf shows, that for strings with the length of 10 the latter solution (splitting & joining) is twice slower than the former solution (using slice), for 100-letter strings it's x5 and for 1000-letter strings it's x50, in Ops/sec it's:

                          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
    

    note that I've changed the 1st and 2d arguments when moving from 10 letters to 100 letters (still I'm surprised that the test for 100 letters runs faster than that for 10 letters).

    0 讨论(0)
  • 2020-11-30 23:45

    Louis's spliceSlice method fails when add value is 0 or other falsy values, here is a fix:

    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 讨论(0)
  • 2020-11-30 23:54

    I solved my problem using this code, is a somewhat replacement for the missing splice.

    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 
    }
    

    I needed to remove a character before/after a certain word, after you get the position the string is split in two and then recomposed by flexibly removing characters using an offset along pos

    0 讨论(0)
  • 2020-11-30 23:55

    I would like to offer a simpler alternative to both the Kumar/Cody and the Louis methods. On all the tests I ran, it performs as fast as the Louis method (see fiddle tests for benchmarks).

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

    You can use it like this:

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

    See Test Results: https://jsfiddle.net/0quz9q9m/5/

    0 讨论(0)
  • 2020-11-30 23:57

    So, whatever adding splice method to a String prototype cant work transparent to spec...

    Let's do some one extend it:

    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;
    }
    
    • Every 3 args group "inserting" in splice style.
    • Special if there is more then one 3 args group, the end off each cut will be the start of next.
      • '0123456789'.splice(4,1,'fourth',8,1,'eighth'); //return '0123fourth567eighth9'
    • You can drop or zeroing the last arg in each group (that treated as "nothing to insert")
      • '0123456789'.splice(-4,2); //return '0123459'
    • You can drop all except 1st arg in last group (that treated as "cut all after 1st arg position")
      • '0123456789'.splice(0,2,null,3,1,null,5,2,'/',8); //return '24/7'
    • if You pass multiple, you MUST check the sort of the positions left-to-right order by youreself!
    • And if you dont want you MUST DO NOT use it like this:
      • '0123456789'.splice(4,-3,'what?'); //return "0123what?123456789"
    0 讨论(0)
  • 2020-11-30 23:59

    Edit

    This is of course not the best way to "splice" a string, I had given this as an example of how the implementation would be, which is flawed and very evident from a split(), splice() and join(). For a far better implementation, see Louis's method.


    No, there is no such thing as a String.splice, but you can try this:

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

    I realise there is no splice function as in Arrays, so you have to convert the string into an array. Hard luck...

    0 讨论(0)
提交回复
热议问题