Gibt es eine Spleißmethode für Zeichenfolgen?

87

Das Javascript splicefunktioniert nur mit Arrays. Gibt es eine ähnliche Methode für Zeichenfolgen? Oder sollte ich meine eigene benutzerdefinierte Funktion erstellen?

Die Methoden substr()und substring()geben nur die extrahierte Zeichenfolge zurück und ändern die ursprüngliche Zeichenfolge nicht. Ich möchte einen Teil aus meiner Zeichenfolge entfernen und die Änderung auf die ursprüngliche Zeichenfolge anwenden. Darüber hinaus replace()funktioniert die Methode in meinem Fall nicht, da ich Teile entfernen möchte, die aus einem Index beginnen und an einem anderen Index enden, genau wie ich es mit der splice()Methode tun kann . Ich habe versucht, meine Zeichenfolge in ein Array zu konvertieren, aber dies ist keine ordentliche Methode.

ProllyGeek
quelle
str.splitkönnte die Funktion sein, die Sie suchen: google.com/#q=javascript+string+split
Anderson Green
1
Was ist los mit str = str.slice()?
Elclanrs
1
Sieht aus wie ein XY-Problem. Was versuchen Sie genau zu tun? Im Gegensatz zu Arrays und Objekten werden Zeichenfolgen nicht als Referenz übergeben. Sie mutieren also keine Zeichenfolgen, erstellen neue oder weisen die neue der alten neu zu.
Elclanrs
6
return string.slice(0, startToSplice) + string.slice(endToSplice);, Nein?
raina77ow

Antworten:

86

Es ist schneller, die Zeichenfolge zweimal in Scheiben zu schneiden:

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

als einen Split gefolgt von einem Join (Kumar Harsh's Methode) wie folgt zu verwenden:

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

Hier ist ein jsperf , der die beiden und einige andere Methoden vergleicht. (jsperf ist seit einigen Monaten nicht mehr verfügbar. Bitte schlagen Sie in den Kommentaren Alternativen vor.)

Obwohl der obige Code Funktionen implementiert, die die allgemeine Funktionalität von reproduzieren splice, ändert die Optimierung des Codes für den vom Fragesteller dargestellten Fall (dh das Hinzufügen von nichts zur geänderten Zeichenfolge) nichts an der relativen Leistung der verschiedenen Methoden.

Louis
quelle
3
Sie können dies global hinzufügen mit: String.prototype.splice = function (index, count, add) { return this.slice(0, index) + (add || "") + this.slice(index + count); } Beachten Sie jedoch, dass es nicht genau so funktioniert wie die Array-Spleißmethode, da Zeichenfolgen unveränderlich sind (Sie können sie nach dem Erstellen nicht mehr ändern). Die Verwendung wäre also wie var s="ss"; s = s.splice(0,1,"t");
William Neely
@WilliamNeely: var StringUtils={'StringSplice':/*func def*/};wäre Standard für die Manipulation von Strings, da Sie gesagt haben, dass es unveränderlich ist.
Mr. Polywhirl
spliceSlice und spliceSplit sind funktional nicht gleich, da Array.prototype.splice negative Indizes akzeptiert: jsfiddle.net/sykteho6/5 .
Martijn
1
@Mzialla Danke, ich habe Code hinzugefügt, um mich darum zu kümmern.
Louis
Das Erstellen von temporären Variablen und das Einführen von Stellen für Off-by-One-Fehler, ganz zu schweigen von Code, dessen Verarbeitung im Gegensatz zu split ("") länger dauert. Splice (...). Join ("") ist ein Kompromiss verdient Beachtung. Das Geschwindigkeitsproblem ist nur dann ein Problem, wenn es ein Problem ist.
Ben Fletcher
15

Bearbeiten

Dies ist natürlich nicht der beste Weg, um einen String zu "spleißen". Ich hatte dies als Beispiel für die Implementierung angegeben, die fehlerhaft und aus einem split (), splice () und join () sehr offensichtlich ist. Für eine weitaus bessere Implementierung siehe Louis ' Methode.


Nein, es gibt keine String.splice, aber Sie können dies versuchen:

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

Mir ist klar, dass es keine spliceFunktion wie in Arrays gibt, daher müssen Sie den String in ein Array konvertieren. Pech...

kumarharsh
quelle
In meinem Fall arbeite ich an einer dynamischen Zeichenfolge, daher muss ich Indizes und keinen Zeichenwert angeben.
ProllyGeek
Ja, das ist leider richtig. Aber Sie können den Index eines Zeichens erhalten, indem Sie String.prototype.indexOf as"asdsd".indexOf('s');
kumarharsh
3
Anstatt str.split zu verwenden, können Sie die ES6-Spread-Syntax wie [...str]
folgt verwenden
5

Hier ist ein nettes kleines Curry, das eine bessere Lesbarkeit bietet (IMHO):

Die Signatur der zweiten Funktion ist identisch mit der Array.prototype.spliceMethode.

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

mutate('101')(1, 1, '1');

Ich weiß, dass es bereits eine akzeptierte Antwort gibt, hoffe aber, dass dies nützlich ist.

Cody
quelle
1
Np. Sie können dies sogar abstrahieren, um beispielsweise einen optionalen 'method'Parameter zuzulassen, sodass Sie einen übergeben Array.prototype[method]und Zeichenfolgen vollständig wie Arrays behandeln können. Mit dieser Option können Sie den eigentlichen Prozess auch auf eine andere Funktion abstrahieren. Wenn keine Zeichenfolge vorhanden ist, geben Sie eine Funktion zurück, die die Zeichenfolge übernimmt und das Curry umkehrt : mutate()(1, 1, '1')('101'); Sie können sogar die Argumente duckType verwenden, um das Curry vom leeren Aufruf zu befreien - und sogar eine Methode selbst kapseln. Wenn Sie diese Dinge benötigen, können Sie in die aussehen Command - Muster though. Einfach hier spucken.
Cody
3

Ich möchte eine einfachere Alternative sowohl zur Kumar / Cody- als auch zur Louis-Methode anbieten. Bei allen Tests, die ich durchgeführt habe, ist die Leistung genauso schnell wie bei der Louis-Methode (Benchmarks siehe Geigen-Tests).

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

Sie können es so verwenden:

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

Siehe Testergebnisse: https://jsfiddle.net/0quz9q9m/5/

Timothy Kanski
quelle
Sie sollten im , otherwise the third argument is not optional. This implementation also doesn't take care of Gegensatz zu anderen Vorschlägen mindestens `+ (insertString ||" ") +` anstelle von `+ insertString + startIndex <0` ausführen. Tolles Beispiel für die Verwendung
YakovL
3

Es scheint eine Menge Verwirrung zu geben, die nur in Kommentaren von elclanrs und raina77ow angesprochen wurde. Lassen Sie mich daher eine klarstellende Antwort posten.

Klärung

Von " string.splice" kann man erwarten, dass es, wie das für Arrays:

  • akzeptiert bis zu 3 Argumente: Startposition, Länge und (optional) Einfügung (Zeichenfolge)
  • Gibt den ausgeschnittenen Teil zurück
  • Ändert die ursprüngliche Zeichenfolge

Das Problem ist, dass die 3D-Anforderung nicht erfüllt werden kann, da Zeichenfolgen unveränderlich sind (siehe: 1 , 2 ). Ich habe hier den engagiertesten Kommentar gefunden :

In JavaScript sind Zeichenfolgen primitive Werttypen und keine Objekte ( spec ). In der Tat, wie von ES5, sie sind eine der nur fünf Werttypen neben null, undefined, numberund boolean. Zeichenfolgen werden nach Wert und nicht nach Referenz zugewiesen und als solche übergeben. Strings sind also nicht nur unveränderlich, sie sind ein Wert . Die Zeichenfolge ändern "hello"zu sein "world"ist wie die von nun an die Nummer 3 der Entscheidung ist die Nummer 4 ... es macht keinen Sinn.

In Anbetracht dessen kann man erwarten, dass das " string.splice" Ding nur:

  • akzeptiert bis zu 2 Argumente: Startposition, Länge (Einfügen macht keinen Sinn, da die Zeichenfolge nicht geändert wird)
  • Gibt den ausgeschnittenen Teil zurück

was ist was substrtut; oder alternativ,

  • akzeptiert bis zu 3 Argumente: Startposition, Länge und (optional) Einfügung (Zeichenfolge)
  • Gibt die geänderte Zeichenfolge zurück (ohne den geschnittenen Teil und mit Einfügung).

Das ist das Thema des nächsten Abschnitts.

Lösungen

Wenn Sie sich für die Optimierung interessieren, sollten Sie wahrscheinlich die Implementierung von Mike verwenden:

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

Die Behandlung des Index außerhalb der Grenzen kann jedoch variieren. Abhängig von Ihren Anforderungen möchten Sie möglicherweise:

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

oder auch

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

Wenn Sie sich nicht für die Leistung interessieren, können Sie Kumars Vorschlag anpassen, der einfacher ist:

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

Performance

Der Leistungsunterschied nimmt mit der Länge der Saite drastisch zu. jsperf zeigt , dass für Strings mit einer Länge von 10 die letztere Lösung (Teilen und Verbinden) doppelt so langsam ist wie die erstere Lösung (mit Slice), für Strings mit 100 Buchstaben x5 und für Strings mit 1000 Buchstaben x50 in Ops / sek es ist:

                      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

Beachten Sie, dass ich das 1. und 2. Argument geändert habe, als ich von 10 Buchstaben auf 100 Buchstaben verschoben habe (trotzdem bin ich überrascht, dass der Test für 100 Buchstaben schneller abläuft als der für 10 Buchstaben).

YakovL
quelle
2

Verwenden Sie einfach substr für string

Ex.

var str = "Hello world!";
var res = str.substr(1, str.length);

Ergebnis = Hallo Welt!

Dinesh Patil
quelle
1

Was auch immer das Hinzufügen einer Spleißmethode zu einem String-Prototyp ist, kann nicht transparent für die Spezifikation sein ...

Lassen Sie uns jemanden erweitern:

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;
}
  • Alle 3 Argumente "Einfügen" im Spleißstil.
  • Speziell wenn es mehr als eine Gruppe mit 3 Argumenten gibt, ist das Ende jedes Schnitts der Anfang des nächsten.
    • '0123456789'.splice (4,1,' vierter ', 8,1,' achter '); // '0123fourth567eighth9' zurückgeben '
  • Sie können das letzte Argument in jeder Gruppe löschen oder auf Null setzen (das als "nichts einzufügen" behandelt wird).
    • '0123456789'.splice (-4,2); // '0123459' zurückgeben '
  • Sie können alle außer dem 1. Arg in der letzten Gruppe löschen (die als "Alle nach der 1. Arg-Position schneiden" behandelt wird).
    • '0123456789'.splice (0,2, null, 3,1, null, 5,2,' / ', 8); // '24 / 7 zurückgeben '
  • Wenn Sie mehrere bestanden haben, MÜSSEN Sie die Art der Positionen von links nach rechts selbst überprüfen!
  • Und wenn Sie nicht wollen, dürfen Sie es NICHT so verwenden:
    • '0123456789'.splice (4, -3,' was? '); // "0123what? 123456789" zurückgeben
Fedor Tykmakov
quelle
0

Die Methode Louis ' Antwort als StringPrototypfunktion:

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

Beispiel:

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

Die spliceSlice- Methode von Louis schlägt fehl, wenn der Add-Wert 0 oder andere falsche Werte ist. Hier ist ein 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);
}
Maryus Martsyalis
quelle
0

Ich habe mein Problem mit diesem Code gelöst, ist ein gewisser Ersatz für den fehlenden Spleiß.

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 
}

Ich musste ein Zeichen vor / nach einem bestimmten Wort entfernen. Nachdem Sie die Position erhalten haben, wird die Zeichenfolge in zwei Teile geteilt und dann durch flexibles Entfernen von Zeichen mithilfe eines Versatzes neu zusammengesetzt pos

Ray Rest
quelle