Frage

Ich weiß, dass wir Strings StringBuilder anhängen können. Gibt es eine Möglichkeit wir Strings voranstellen können (das heißt hinzufügen Strings vor einem String) mit StringBuilder so können wir die Leistungsvorteile halten, die Angebote StringBuilder?

War es hilfreich?

Lösung

Mit der Insert-Methode mit dem Positionsparameter auf 0 gesetzt, würde die gleichen wie Prepending (d.h. am Anfang Einsetzen).

An example is : varStringBuilder.insert(0, "someThing");

Es funktioniert sowohl für C # und Java

Andere Tipps

Voranstellen eine Zeichenfolge wird in der Regel zu kopieren alles benötigt nach dem Einsetzen etwas in den Trägern Array zeigen zurück, so dass es nicht so schnell sein wird am Ende als anhängt.

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

aStringBuilder.insert(0, "newText");

Wenn Sie eine hohe Leistung mit viel wird vorangestellt benötigen, müssen Sie Ihre eigene Version von StringBuilder schreiben (oder jemand anderes verwenden). Mit dem Standard-StringBuilder (obwohl technisch könnte es anders implementiert werden) einzufügen erfordern Kopieren von Daten nach dem Einfügepunkt. Einfügen von n Stück Text kann O nehmen (n ^ 2) Zeit.

Ein naiver Ansatz wäre ein in den Pufferträger char[] sowie die Längenkorrektur hinzuzufügen. Wenn es nicht genug Platz für einen prepend ist, um mehr die Daten nach oben bewegen, als unbedingt erforderlich ist. Dies kann die Leistung bringt wieder auf O (n log n) (glaube ich). Eine verfeinerte Methode ist, den Puffer zyklisch zu machen. Auf diese Weise wird der Ersatzraum an beiden Enden des Arrays angrenzt.

Sie können 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!

Ich habe nicht verwendet es aber Seile für Java Klingt faszinierend. Der Projektname ein Wortspiel ist, verwenden Sie ein Rope anstelle eines String für ernsthafte Arbeit. Ruft um die Leistungseinbuße für Prepending und andere Operationen. Ein Blick wert, wenn Sie vorhaben, viel dies zu tun.

  

Ein Seil ist ein Hochleistungs   Ersatz für Streicher. Das   Datenstruktur, beschrieben im Detail in der   "Seile: eine Alternative zu Strings",   bietet asymptotisch besser   Leistung als sowohl String und   String für gemeinsamen Zeichenfolge   Modifikationen wie prepend, hängen,   löschen und einfügen. Wie Streicher,   Seile sind unveränderlich und deshalb   in Multi-Threaded zur Verwendung gut geeignet,   Programmierung.

Sie können die Zeichenfolge in umgekehrter bauen und dann das umzukehren. Sie sind gegen einen O (n) Kosten anstelle eines O (n ^ 2) im schlechtesten Fall Kosten.

Hier ist, was Sie tun können, wenn Sie in der Java-Klasse Stringvoranstellen wollen:

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

Wenn ich Sie richtig verstehe, die insert-Methode wie es aussieht, werde tun, was Sie wollen. Legen Sie einfach die Zeichenfolge bei Offset 0.

Versuchen Sie es mit Insert ()

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

Geht man von den anderen Kommentaren, gibt es keine Standard schnelle Möglichkeit, dies zu tun. Mit String .Insert(0, "text") die etwa nur 1-3x so schnell wie quälend langsam String-Verkettung mit (basierend auf> 10000 concats), ist so unter einer Klasse potenziell schnellen tausende Male vorangestellt wird!

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

Der Code wurde getestet ziemlich viel, aber ich kann nicht garantieren, es von Fehlern frei 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)
    }
}

Sie können eine Erweiterung schaffen für Stringbuilder, sich mit einer einfachen Klasse:

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;

Nach oben jeder Klasse, dass Sie die Stringbuilder in und jederzeit Sie verwenden Intelli-Sense mit einem Stringvariable, die Prepend und PrependLine Methoden verwenden möchten, wird sich zeigen. Denken Sie daran, dass, wenn Sie Prepend verwenden, müssen Sie in umgekehrter Reihenfolge vorangestellt wird, als wenn Sie wurden Anfügen.

Dies sollte funktionieren:

aStringBuilder = "newText" + aStringBuilder; 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top