C#またはJava:文字列の前にStringBuilderを追加しますか?


102

を使用して文字列を追加できることはわかっていますStringBuilder。提供StringBuilderするパフォーマンス上の利点を維持できるように、を使用して文字列を先頭に追加する(つまり、文字列の前に文字列を追加する)方法はありStringBuilderますか?


私はあなたの質問を理解していません
モーリスペリー

5
先頭に追加します。単語は先頭に追加されます。文字列の事前追加は、文字列の両端に一度に追加するようなものである必要があると思いますか?
Joel Mueller、

回答:


164

位置パラメーターを0に設定して挿入メソッドを使用することは、先頭に追加する(つまり、最初に挿入する)ことと同じです。

例は次のとおりです。 varStringBuilder.insert(0, "someThing");

C#Javaの両方で機能します



関連するAPIの正しいJavadocは次のとおりです。docs.oracle.com/javase/1.5.0/docs/api/java/lang/...
スレッド

29

文字列の先頭に追加するには、通常、挿入ポイントの後のすべてをバッキング配列の一部にコピーする必要があるため、末尾に追加するほど速くはありません。

しかし、Javaでこれを行うことができます(C#でも同じですが、メソッドはと呼ばれますInsert)。

aStringBuilder.insert(0, "newText");

11

プリペンドをたくさん付けて高いパフォーマンスが必要な場合は、独自のバージョンのを作成するStringBuilder(または他の誰かのバージョンを使用する)必要があります。標準ではStringBuilder(技術的には異なる方法で実装できます)、挿入では挿入ポイントの後にデータをコピーする必要があります。n個のテキストを挿入すると、O(n ^ 2)時間かかる場合があります。

素朴なアプローチはchar[]、長さだけでなくバッキングバッファーにオフセットを追加することです。先頭に追加するための十分なスペースがない場合は、必要以上にデータを上に移動します。これにより、パフォーマンスをO(n log n)に戻すことができます(私はそう思います)。より洗練されたアプローチは、バッファを循環させることです。このようにして、アレイの両端のスペアスペースが隣接します。


5

あなたは拡張メソッドを試すことができます:

/// <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!

5

文字列を逆に作成してから、結果を逆にすることができます。O(n ^ 2)の最悪の場合のコストではなく、O(n)のコストが発生します。


2
これは、個々の文字を追加する場合にのみ機能します。それ以外の場合は、追加した各文字列を逆にする必要があります。これは、文字列のサイズと数に応じて、節約のすべてではないにしてもほとんどを消費します。
そり

4

私はそれを使ったことはありませんが、Javaサウンド用のロープは興味深いものです。プロジェクト名は言葉遊びです。深刻な作業には文字列ではなくロープを使用してください。付加やその他の操作によるパフォーマンスの低下を回避します。あなたがこれをたくさんするつもりなら、一見の価値があります。

ロープは、ストリングの高性能な代替品です。「ロープ:文字列の代替」で詳細に説明されているデータ構造は、先頭に追加、追加、削除、挿入などの一般的な文字列の変更に対して、文字列と文字列バッファの両方よりも漸近的に優れたパフォーマンスを提供します。文字列と同様に、ロープは不変であるため、マルチスレッドプログラミングでの使用に適しています。


4

JavaのStringBuilderクラスを使用して先頭に追加したい場合は、次のことができます。

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

3

私があなたを正しく理解していれば、挿入メソッドはあなたが望むことをするように見えます。文字列をオフセット0に挿入するだけです。


2

Insert()を使用してみてください

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

2

他のコメントから判断すると、これを行う標準的な簡単な方法はありません。StringBuilderの.Insert(0, "text")使用は、ひどく遅い文字列連結(> 10000連結に基づく)を使用する場合に比べて、約1〜3倍の速さで済むため、以下のクラスは、何千倍も速く潜在的に追加するクラスです。

私は、次のようないくつかの他の基本的な機能を含めましたappend()subString()そしてlength()どちらも追加し、前に付加が遅くなるのStringBuilderが追加よりも3倍に高速で約2倍異なるなど。StringBuilderと同様に、このクラスのバッファーは、テキストが古いバッファーサイズをオーバーフローすると自動的に増加します。

コードはかなりテストされていますが、バグがないことは保証できません。

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

1

簡単なクラスを使用して、StringBuilderの拡張機能を自分で作成できます。

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

次に、追加するだけです:

using Application.Code.Helpers;

StringBuilderを使用するクラスの先頭に、またStringBuilder変数でインテリセンスを使用するときはいつでも、PrependメソッドとPrependLineメソッドが表示されます。Prependを使用する場合は、Appendの場合とは逆の順序でPrependする必要があることに注意してください。


0

これはうまくいくはずです:

aStringBuilder = "newText" + aStringBuilder; 

.NETでは、これはtypeの値では完全に機能しますが、typeの値でstringは機能しませんStringBuilder。@ScubaSteveからの回答はうまくいきます。
Contango 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.