C # 또는 Java : 문자열 앞에 StringBuilder를 추가 하시겠습니까?


102

을 사용하여 문자열을 추가 할 수 있다는 것을 알고 있습니다 StringBuilder. 제공 StringBuilder하는 성능 이점을 유지할 수 있도록을 사용하여 문자열 앞에 추가 (즉, 문자열 앞에 문자열 추가) 할 수있는 방법이 StringBuilder있습니까?


질문을 이해하지 못합니다
Maurice Perry

5
앞에 추가합니다. 단어가 앞에 추가됩니다. 문자열을 미리 추가하는 것은 문자열의 양쪽 끝에 한 번에 추가하는 것과 같아야합니다.
Joel Mueller

답변:


164

위치 매개 변수를 0으로 설정하고 삽입 방법을 사용하는 것은 앞에 추가하는 것과 같습니다 (즉, 시작 부분에 삽입).

예 : varStringBuilder.insert(0, "someThing");

C #Java 모두에서 작동합니다.



관련 API에 대한 올바른 JavaDoc은 다음과 같습니다. docs.oracle.com/javase/1.5.0/docs/api/java/lang/…
Sled

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

나는 그것을 사용하지 않았지만 Ropes For Java Sounds는 흥미 롭습니다. 프로젝트 이름은 단어 놀이입니다 . 진지한 작업을 위해 문자열 대신 로프 를 사용하십시오 . 준비 및 기타 작업에 대한 성능 저하를 피합니다. 이 일을 많이한다면 한 번 볼 가치가 있습니다.

로프는 Strings의 고성능 대체품입니다. "로프 : 문자열의 대안"에 자세히 설명 된 데이터 구조는 접두사, 추가, 삭제 및 삽입과 같은 일반적인 문자열 수정에 대해 String 및 StringBuffer보다 점근 적으로 더 나은 성능을 제공합니다. 문자열과 마찬가지로 로프는 불변이므로 다중 스레드 프로그래밍에 사용하기에 적합합니다.


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")를 사용하는 것은 고통스럽게 느린 String 연결 (> 10000 개의 연결을 기반으로 함)을 사용하는 것보다 약 1-3 배 빠르므로 다음은 잠재적으로 수천 배 더 빨리 앞에 추가하는 클래스입니다!

나는 다음과 같은 몇 가지 다른 기본적인 기능을 포함 시켰습니다 append(), subString()그리고 length()등 모두 추가하고 앞에 추가 느린의 StringBuilder가 추가보다 3 배 약 두 배 빠른 다릅니다. 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를 사용할 때는 Appending보다 역순으로 Prepend를 사용해야합니다.


0

이것은 작동합니다.

aStringBuilder = "newText" + aStringBuilder; 

.NET에서 이것은 type 값에 완벽하게 작동 string하지만 type 값에 대해서는 작동하지 않습니다 StringBuilder. @ScubaSteve의 답변이 잘 작동합니다.
Contango 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.