2009-04-10 8 views
82

Ich weiß, wir können Strings mit StringBuilder anhängen. Gibt es eine Möglichkeit, Strings voranzustellen (d. H. Strings vor einem String hinzuzufügen), indem wir StringBuilder verwenden, damit wir die Leistungsvorteile beibehalten können, die StringBuilder bietet?C# oder Java: Zeichenfolgen mit StringBuilder vorgeben?

+0

Ich verstehe Ihre Frage nicht –

+5

Prepend. Das Wort wird vorangestellt. Preadding einer Zeichenfolge muss etwas wie das Hinzufügen zu beiden Enden einer Zeichenfolge auf einmal sein, denke ich? –

Antwort

119

Die Verwendung der Einfügemethode mit dem Positionsparameter, der auf 0 gesetzt ist, wäre dasselbe wie das Voranstellen (d. H. Einfügen am Anfang).

Es funktioniert sowohl für C# und Java

+7

StringBuilder einfügen für Java: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html#insert() (% 20boolean) –

+0

Das richtige JavaDoc für die relevante API ist : http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html#insert(int,int%20java.lang.CharSequence%29 – ArtB

5
StringBuilder str = new StringBuilder(); 
str.Insert(0, "text"); 

Edit: formated Code

2

Versuchen Insert()

StringBuilder MyStringBuilder = new StringBuilder("World!"); 
MyStringBuilder.Insert(0,"Hello "); // Hello World! 
23

Voranstellen einer Zeichenfolge verwendet, wird in der Regel zu kopieren alles benötigen nach dem Einsetzen etwas Punkt zurück in der Backing-Array, so wird es nicht so schnell wie das Anhängen an das Ende.

Aber man kann es so in Java tun (in C# ist es das gleiche, aber die Methode ist Insert genannt):

aStringBuilder.insert(0, "newText"); 
4

Wenn ich Sie richtig verstehe, die insert method sieht aus wie es, was zu tun, Sie wollen. Legen Sie einfach die Zeichenfolge auf 0

5

versetzt Sie könnten eine Verlängerung Methode versuchen:

/// <summary> 
/// kind of a dopey little one-off for StringBuffer, but 
/// an example where you can get crazy with extension methods 
/// </summary> 
public static void Prepend(this StringBuilder sb, string s) 
{ 
    sb.Insert(0, s); 
} 

StringBuilder sb = new StringBuilder("World!"); 
sb.Prepend("Hello "); // Hello World! 
10

Wenn Sie eine hohe Leistung mit viel wird vorangestellt benötigen, müssen Sie Ihre eigene Version von StringBuilder (oder Verwendung schreiben von jemand anderem). Mit dem Standard StringBuilder (obwohl technisch könnte es anders implementiert werden) einfügen erfordern das Kopieren von Daten nach dem Einfügepunkt. Das Einfügen von n Textstücken kann O (n^2) dauern.

Ein naive Ansatz wäre, einen Offset in den Puffer char[] Puffer sowie die Länge hinzuzufügen. Wenn nicht genügend Platz für einen Vorlauf vorhanden ist, verschieben Sie die Daten um mehr als unbedingt erforderlich. Dies kann die Leistung zurück auf O (n log n) bringen (denke ich). Ein verfeinerterer Ansatz besteht darin, den Puffer zyklisch zu machen. Auf diese Weise wird der Ersatzraum an beiden Enden des Arrays zusammenhängend.

5

Ich habe es nicht verwendet, aber Ropes For Java klingt faszinierend. Der Projektname ist ein Wortspiel, verwenden Sie eine Rope anstelle einer String für ernsthafte Arbeit. Überwindet die Leistungseinbuße für vorbereitende und andere Vorgänge. Einen Blick wert, wenn du viel davon machst.

Ein Seil ist ein Hochleistungs Ersatz für Saiten. Die Datenstruktur, beschrieben im Detail in „Ropes: eine Alternative zu Strings“, bietet asymptotisch bessere Leistung als sowohl Streich- und Stringbuffer für die gemeinsame Zeichenfolge Modifikationen wie prepend, hängen, löschen und einzufügen. Wie Strings, Seile sind unveränderlich und daher gut geeignet für den Einsatz in Multi-Thread Programmierung.

5

Sie könnten die Zeichenfolge in umgekehrter Reihenfolge erstellen und dann das Ergebnis umkehren. Sie erhalten einen O (n) -Kosten statt eines O (n^2) Worst-Case-Kosten.

+2

Das funktioniert nur, wenn Sie einzelne anhängen Andernfalls müssten Sie jede hinzugefügte Zeichenfolge umkehren, was die meisten Einsparungen zunichte machen würde, abhängig von der Größe und Anzahl der Zeichenfolgen. – ArtB

2

Nach den anderen Kommentaren zu urteilen, gibt es keine schnelle Standardmethode, dies zu tun. Die Verwendung von StringBuilders .Insert(0, "text") ist ungefähr nur 1-3x so schnell wie die Verwendung einer schmerzhaft langsamen String-Verkettung (basierend auf> 10000 concats), daher ist unten eine Klasse, die potenziell tausende Male schneller vorangestellt werden kann!

Ich habe einige andere grundlegende Funktionen enthalten wie append(), subString() und length() usw. Beide Appends und wird vorangestellt von etwa doppelt so schnell variieren langsamer zu 3x als String anhängt. Wie StringBuilder erhöht sich der Puffer in dieser Klasse automatisch, wenn der Text die alte Puffergröße überschreitet.

Der Code wurde ziemlich oft getestet, aber ich kann nicht garantieren, dass er frei von Fehlern ist.

class Prepender 
{ 
    private char[] c; 
    private int growMultiplier; 
    public int bufferSize;  // Make public for bug testing 
    public int left;   // Make public for bug testing 
    public int right;   // Make public for bug testing 
    public Prepender(int initialBuffer = 1000, int growMultiplier = 10) 
    { 
     c = new char[initialBuffer]; 
     //for (int n = 0; n < initialBuffer; n++) cc[n] = '.'; // For debugging purposes (used fixed width font for testing) 
     left = initialBuffer/2; 
     right = initialBuffer/2; 
     bufferSize = initialBuffer; 
     this.growMultiplier = growMultiplier; 
    } 
    public void clear() 
    { 
     left = bufferSize/2; 
     right = bufferSize/2; 
    } 
    public int length() 
    { 
     return right - left; 
    } 

    private void increaseBuffer() 
    { 
     int nudge = -bufferSize/2; 
     bufferSize *= growMultiplier; 
     nudge += bufferSize/2; 
     char[] tmp = new char[bufferSize]; 
     for (int n = left; n < right; n++) tmp[n + nudge] = c[n]; 
     left += nudge; 
     right += nudge; 
     c = new char[bufferSize]; 
     //for (int n = 0; n < buffer; n++) cc[n]='.'; // For debugging purposes (used fixed width font for testing) 
     for (int n = left; n < right; n++) c[n] = tmp[n]; 
    } 

    public void append(string s) 
    { 
     // If necessary, increase buffer size by growMultiplier 
     while (right + s.Length > bufferSize) increaseBuffer(); 

     // Append user input to buffer 
     int len = s.Length; 
     for (int n = 0; n < len; n++) 
     { 
      c[right] = s[n]; 
      right++; 
     } 
    } 
    public void prepend(string s) 
    { 
     // If necessary, increase buffer size by growMultiplier 
     while (left - s.Length < 0) increaseBuffer();    

     // Prepend user input to buffer 
     int len = s.Length - 1; 
     for (int n = len; n > -1; n--) 
     { 
      left--; 
      c[left] = s[n]; 
     } 
    } 
    public void truncate(int start, int finish) 
    { 
     if (start < 0) throw new Exception("Truncation error: Start < 0"); 
     if (left + finish > right) throw new Exception("Truncation error: Finish > string length"); 
     if (finish < start) throw new Exception("Truncation error: Finish < start"); 

     //MessageBox.Show(left + " " + right); 

     right = left + finish; 
     left = left + start; 
    } 
    public string subString(int start, int finish) 
    { 
     if (start < 0) throw new Exception("Substring error: Start < 0"); 
     if (left + finish > right) throw new Exception("Substring error: Finish > string length"); 
     if (finish < start) throw new Exception("Substring error: Finish < start"); 
     return toString(start,finish); 
    } 

    public override string ToString() 
    { 
     return new string(c, left, right - left); 
     //return new string(cc, 0, buffer);  // For debugging purposes (used fixed width font for testing) 
    } 
    private string toString(int start, int finish) 
    { 
     return new string(c, left+start, finish-start); 
     //return new string(cc, 0, buffer);  // For debugging purposes (used fixed width font for testing) 
    } 
} 
0

Diese Arbeit sollte:

aStringBuilder = "newText" + aStringBuilder; 
+0

In .NET funktioniert das perfekt mit Werten vom Typ 'string', aber funktioniert nicht mit Werten vom Typ 'StringBuilder'. Die Antwort von @ScubaSteve funktioniert gut. – Contango

1

Sie eine Erweiterung für String sich mit einer einfachen Klasse schaffen könnte:

namespace Application.Code.Helpers 
{ 
    public static class StringBuilderExtensions 
    { 
     #region Methods 

     public static void Prepend(this StringBuilder sb, string value) 
     { 
      sb.Insert(0, value); 
     } 

     public static void PrependLine(this StringBuilder sb, string value) 
     { 
      sb.Insert(0, value + Environment.NewLine); 
     } 

     #endregion 
    } 
} 

Dann fügen Sie einfach:

using Application.Code.Helpers; 

Ganz oben in jeder Klasse, die Sie verwenden möchten Wenn Sie intelli-sense mit einer StringBuilder-Variablen verwenden, werden die Methoden Prepend und PrependLine angezeigt. Denken Sie daran, dass Sie Prepend in umgekehrter Reihenfolge vorgeben müssen, als wenn Sie Appending verwenden würden.

Verwandte Themen