it-swarm.com.de

split-String nur bei der ersten Instanz des angegebenen Zeichens

In meinem Code teile ich eine Zeichenfolge basierend auf _ und greife das zweite Element im Array.

var element = $(this).attr('class');
var field = element.split('_')[1];

Nimmt good_luck und liefert mir luck. Funktioniert super!

Aber jetzt habe ich eine Klasse, die wie good_luck_buddy aussieht. Wie bekomme ich mein Javascript, um den zweiten _ zu ignorieren und mir luck_buddy zu geben?

Ich habe dieses var field = element.split(new char [] {'_'}, 2); in einer c # stackoverflow-Antwort gefunden, aber es funktioniert nicht. Ich habe es bei jsFiddle versucht ...

195
Ofeargall

Verwenden Sie Erfassen von Klammern :

"good_luck_buddy".split(/_(.+)/)[1]
"luck_buddy"

Sie sind definiert als

Wenn separator erfasste Klammern enthält, sind übereinstimmende Ergebnisse im Array zurückgegeben.

In diesem Fall möchten wir also bei _.+ teilen (d. H., Das Trennzeichen ist eine mit _ beginnende Unterzeichenfolge) , aber auch das Ergebnis einen Teil unseres Trennzeichens enthalten (d. H. Alles after _).

In diesem Beispiel ist unser Trennzeichen (übereinstimmend _(.+)) _luck_buddy und die erfasste Gruppe (innerhalb des Trennzeichens) lucky_buddy. Ohne die erfassende Klammer wäre der luck_buddy (übereinstimmender .+) nicht im Ergebnis-Array enthalten, da bei einfachen split die Trennzeichen nicht im Ergebnis enthalten sind.

307
Mark F

Wofür brauchen Sie reguläre Ausdrücke und Arrays?

myString = myString.substring(myString.indexOf('_')+1)

var myString= "hello_there_how_are_you"
myString = myString.substring(myString.indexOf('_')+1)
console.log(myString)

191
kennebec

Ich vermeide um jeden Preis RegExp. Hier können Sie noch etwas tun:

"good_luck_buddy".split('_').slice(1).join('_')
23
yonas

Ersetzen Sie die erste Instanz durch einen eindeutigen Platzhalter, und trennen Sie dann von dort aus.

"good_luck_buddy".replace(/\_/,'&').split('&')

["good","luck_buddy"]

Dies ist sinnvoller, wenn beide Seiten der Aufteilung benötigt werden.

10
sebjwallace

Sie können den regulären Ausdruck wie folgt verwenden:

var arr = element.split(/_(.*)/)
Sie können den zweiten Parameter verwenden, der die Grenze der Aufteilung angibt Das heißt: var Feld = Element.split ('_', 1) [1];
5
Chandu

Der String.split von Javascript kann die tatsächliche Anzahl der Splits leider nicht einschränken. Es gibt ein zweites Argument, das angibt, wie viele der geteilten Elemente tatsächlich zurückgegeben werden. Dies ist in Ihrem Fall nicht hilfreich. Die Lösung wäre, die Zeichenfolge aufzuteilen, das erste Element zu verschieben und dann die restlichen Elemente wieder zusammenzufügen:

var element = $(this).attr('class');
var parts = element.split('_');

parts.shift(); // removes the first item from the array
var field = parts.join('_');
3
Alex Vidal

Schnellste Lösung?

Ich habe einige Benchmarks ausgeführt, und diese Lösung hat enorm gewonnen:1

str.slice(str.indexOf(delim) + delim.length)

// as function
function gobbleStart(str, delim) {
    return str.slice(str.indexOf(delim) + delim.length);
}

// as polyfill
String.prototype.gobbleStart = function(delim) {
    return this.slice(this.indexOf(delim) + delim.length);
};

Leistungsvergleich mit anderen Lösungen

Der einzige enge Konkurrent war dieselbe Codezeile, außer dass substr anstelle von split verwendet wurde.

Andere Lösungen, die ich ausprobierte, split oder RegExps, hatten einen großen Performance-Erfolg und waren etwa 2 Größenordnungen langsamer. Die Verwendung von join für die Ergebnisse von split führt natürlich zu einem zusätzlichen Performance-Nachteil.

Warum sind sie langsamer? Jedes Mal, wenn ein neues Objekt oder Array erstellt werden muss, muss JS einen Teil des Speichers vom Betriebssystem anfordern. Dieser Prozess ist sehr langsam. 

Hier sind einige allgemeine Richtlinien, falls Sie Benchmarks verfolgen:

  • Neue dynamische Speicherzuweisungen für Objekte {} oder Arrays [] (wie die von split erstellte) verursachen einen hohen Performance-Preis.
  • RegExp-Suchen sind komplizierter und daher langsamer als String-Suchen.
  • Wenn Sie bereits über ein Array verfügen, ist das Zerstören von Arrays ungefähr so ​​schnell wie das explizite Indizieren und sieht fantastisch aus.

Entfernen über die erste Instanz hinaus

Hier ist eine Lösung, die bis zur n-ten Instanz reicht. Es ist nicht ganz so schnell, aber auf die Frage des OPs ist gobble(element, '_', 1) immer noch zweimal schneller als eine RegExp- oder split-Lösung und kann mehr:

/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
  let remain = limit;
  if (limit <= 0) { // set remain to count of delim - num to leave
    let i = 0;
    while (i < haystack.length) {
      const found = haystack.indexOf(needle, i);
      if (found === -1) {
        break;
      }
      remain++;
      i = found + needle.length;
    }
  }

  let i = 0;
  while (remain > 0) {
    const found = haystack.indexOf(needle, i);
    if (found === -1) {
      break;
    }
    remain--;
    i = found + needle.length;
  }
  return haystack.slice(i);
}

Bei der obigen Definition würde gobble('path/to/file.txt', '/') den Namen der Datei angeben und gobble('prefix_category_item', '_', 1) würde das Präfix wie die erste Lösung in dieser Antwort entfernen.


  1. Tests wurden in Chrome 70.0.3538.110 auf macOSX 10.14 ausgeführt.
0

Ich brauche die zwei Teile von string.

const full_name = 'Maria do Bairro';
const [first_name, last_name] = full_name.split(/(?<=^[^ ]+) /);
console.log(first_name);
console.log(last_name);

Hier ist eine RegExp, die den Trick macht.

'good_luck_buddy' . split(/^.*?_/)[1] 

Zuerst zwingt es das Match, vom Start aus mit dem '^' zu beginnen. Dann stimmt es mit einer beliebigen Anzahl von Zeichen überein, die nicht '_' sind, mit anderen Worten: alle Zeichen vor dem ersten '_'.

Das '?' bedeutet eine minimale Anzahl von Zeichen , die das gesamte Muster übereinstimmen, sind , die mit '. *?' übereinstimmen. weil es folgtby '_', das dann als letztes Zeichen in das Match aufgenommen wird. 

Deshalb verwendet split () einen solchen übereinstimmenden Teil als Teiler und entfernt ihn aus den Ergebnissen. So entfernt es alles Bis einschließlich des ersten '_' und Gibt Ihnen den Rest als 2. Element von Das Ergebnis. Das erste Element ist "" und repräsentiert den Teil vor dem übereinstimmenden Teil. Es ist "", Weil das Spiel am Anfang beginnt.

Es gibt andere RegExps, die als Gut funktionieren, wie /_(.*)/ von Chanduin einer vorherigen Antwort. 

Das /^.*?_/ hat den Vorteil, dass Sie Verstehen können, was es tut, ohne ___ über die besondere Rolle Bescheid wissen zu müssen Gruppen erfassen mit replace ().

0
Panu Logic

Verwenden Sie die Zeichenfolge replace() mit einem regex :

var result = "good_luck_buddy".replace(/.*?_/, "");
console.log(result);

Dieser Ausdruck entspricht 0 oder mehr Zeichen vor dem ersten _ und dem _ selbst. Die Übereinstimmung wird dann durch eine leere Zeichenfolge ersetzt.

0
James T

Das hat für mich auf Chrome + FF funktioniert:

"foo=bar=beer".split(/^[^=]+=/)[1] // "bar=beer"
"foo==".split(/^[^=]+=/)[1] // "="
"foo=".split(/^[^=]+=/)[1] // ""
"foo".split(/^[^=]+=/)[1] // undefined

Wenn Sie auch den Schlüssel benötigen, versuchen Sie Folgendes:

"foo=bar=beer".split(/^([^=]+)=/) // Array [ "", "foo", "bar=beer" ]
"foo==".split(/^([^=]+)=/) // [ "", "foo", "=" ]
"foo=".split(/^([^=]+)=/) // [ "", "foo", "" ]
"foo".split(/^([^=]+)=/) // [ "foo" ]

//[0] = ignored (holds the string when there's no =, empty otherwise)
//[1] = hold the key (if any)
//[2] = hold the value (if any)
0
oriadam

Für Anfänger wie mich, die nicht an Regular Expression gewöhnt sind, funktionierte diese Lösung: 

   var field = "Good_Luck_Buddy";
   var newString = field.slice( field.indexOf("_")+1 );

die Methode slice () extrahiert einen Teil einer Zeichenfolge und gibt eine neue Zeichenfolge zurück. Die Methode indexOf () gibt die Position des ersten gefundenen Wertes eines angegebenen Werts in einer Zeichenfolge zurück.

0

Die Lösung von Mark F ist großartig, wird jedoch von alten Browsern nicht unterstützt. Kennebecs Lösung ist großartig und wird von alten Browsern unterstützt, Regex jedoch nicht.

Wenn Sie also nach einer Lösung suchen, die Ihre Zeichenfolge nur einmal teilt, die von alten Browsern unterstützt wird und Regex unterstützt, ist hier meine Lösung:

String.prototype.splitOnce = function(regex)
{
    var match = this.match(regex);
    if(match)
    {
        var match_i = this.indexOf(match[0]);
        
        return [this.substring(0, match_i),
        this.substring(match_i + match[0].length)];
    }
    else
    { return [this, ""]; }
}

var str = "something/////another thing///again";

alert(str.splitOnce(/\/+/)[1]);

0
pmrotule