文字列のスプライス方法はありますか?


87

Javascriptspliceは配列でのみ機能します。文字列に同様の方法はありますか?または、独自のカスタム関数を作成する必要がありますか?

substr()、およびsubstring()方法はのみ抽出された文字列を返すと、元の文字列を変更しません。私がやりたいのは、文字列から一部を削除し、元の文字列に変更を適用することです。さらに、このメソッドでreplace()実行できるのとまったく同じように、インデックスから始まり、他のインデックスで終わる部分を削除したいので、このメソッドは機能しませんsplice()。文字列を配列に変換しようとしましたが、これは適切な方法ではありません。


str.splitあなたが探している関数かもしれません:google.com/#q=javascript+string+split
アンダーソングリーン

1
何が問題になっていstr = str.slice()ますか?
elclanrs 2013

1
XYの問題のように見えますが、正確に何をしようとしていますか?配列やオブジェクトとは異なり、文字列は参照によって渡されないため、文字列を変更したり、新しい文字列を作成したり、新しい文字列を古い文字列に再割り当てしたりしません。
elclanrs 2013


6
return string.slice(0, startToSplice) + string.slice(endToSplice);、 番号?
raina77ow 2013

回答:


88

次のように、文字列を2回スライスする方が高速です。

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

これは、2つの方法と他のいくつかの方法を比較する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");
ウィリアム・ニーリー

@WilliamNeely:var StringUtils={'StringSplice':/*func def*/};不変であると言ったように、文字列操作の標準になります。
ポリワール氏2014年

Array.prototype.spliceが負のインデックスを受け入れるため、spliceSliceとspliceSplitは機能的に等しくありません:jsfiddle.net/sykteho6/5
Martijn 2016

1
@Mziallaありがとう、私はそれを処理するためのコードを追加しました。
Louis

split( "")。splice(...)。join( "")とは対照的に、人間が処理するのに時間がかかるコードは言うまでもなく、一時変数を作成し、オフバイワンエラーの場所を導入することはトレードオフです。検討に値する。速度の問題は、それが問題である場合にのみ問題になります。
ベンフレッチャー

15

編集

もちろん、これは文字列を「スプライス」するための最良の方法ではありません。実装がどのようになるかの例としてこれを挙げました。これには欠陥があり、split()、splice()、join()から非常に明白です。はるかに優れた実装については、Louisの方法を参照してください。


いいえ、のようなものはありませんが、String.spliceこれを試すことができます:

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

splice配列のような関数はないので、文字列を配列に変換する必要があります。不運...


私の場合、動的文字列で作業しているので、文字値ではなくインデックスを指定する必要があります。
ProllyGeek 2013

はい、それは残念ながら正しいです。ただし、String.prototype.indexOfを次のように使用して文字のインデックスを取得できます"asdsd".indexOf('s');
kumarharsh 2013

3
:代わりにstr.splitを使用して、あなたはそのようES6スプレッドの構文を使用することができます[...str]
ロビー

5

これが読みやすさを向上させる素敵な小さなカレーです(IMHO):

2番目の関数のシグネチャは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 + startIndex < 0`の代わりに少なくとも` +(insertString || "")+ `を実行する必要があります。ただし、使用法の
優れた

3

elclanrsとraina77owのコメントだけで対処された混乱がたくさんあるようですので、明確な答えを投稿させてください。

明確化

" string.splice"から、配列の場合のように、それを期待するかもしれません。

  • 最大3つの引数を受け入れます:開始位置、長さ、および(オプションで)挿入(文字列)
  • 切り抜いた部分を返します
  • 元の文字列を変更します

問題は、文字列が不変であるために3D要件を満たすことができないことです(関連:12を、私はほとんど専用のコメントを見つけた)ここに

JavaScriptでは、文字列はプリミティブ値型でありオブジェクト(spec)ではありません。実際には、ES5のように、彼らは一緒にのみ、5値の型の一つだnullundefinednumberboolean。文字列はによって割り当てられた値ではありません参照することにより、そのようなものとして渡されます。したがって、文字列は不変であるだけでなく、です。文字列"hello"をに変更すること"world"は、これから3番が4番であると決定するようなものです...それは意味がありません。

したがって、それを考慮に入れると、「string.splice」のことは次のことだけを期待するかもしれません。

  • 最大2つの引数を受け入れます:開始位置、長さ(文字列は変更されないため、挿入は意味がありません)
  • 切り抜いた部分を返します

これは何ですか substr。または、あるいは、

  • 最大3つの引数を受け入れます:開始位置、長さ、および(オプションで)挿入(文字列)
  • 変更された文字列を返します(カット部分なしで挿入あり)

これは次のセクションの主題です。

ソリューション

最適化に関心がある場合は、おそらくマイクの実装を使用する必要があります。

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、Ops /で、長さが10の文字列の場合、後者のソリューション(分割と結合)は前者のソリューション(スライスを使用)の2倍遅く、100文字の文字列の場合はx5、1000文字の文字列の場合はx50であることを示しています。秒それは:

                      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文字に移動するときに、1番目と2番目の引数を変更したことに注意してください(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つの引数ごとにスプライススタイルで「挿入」します。
  • 3つの引数グループが複数ある場合は特別です。各カットの終わりが次の始まりになります。
    • '0123456789'.splice(4,1、' fourth '、8,1、' eighth '); //「0123fourth567eighth9」を返します
  • 各グループの最後の引数(「挿入するものがない」として扱われる)を削除またはゼロにすることができます
    • '0123456789'.splice(-4,2); //「0123459」を返します
  • 最後のグループの最初の引数を除くすべてを削除できます(「最初の引数の位置の後にすべてカット」として扱われます)
    • '0123456789'.splice(0,2、null、3,1、null、5,2、' / '、8); //「24/7」を返します
  • 複数合格する場合は、左から右への位置の並べ替えを自分で確認する必要があります。
  • そして、あなたが望まないならば、あなたはそれをこのように使わないでください:
    • '0123456789'.splice(4、-3、' what? '); //「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

加算値が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 
}

特定の単語の前後の文字を削除する必要がありました。位置を取得した後、文字列は2つに分割され、オフセットを使用して文字を柔軟に削除することで再構成されます。 pos

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.