C# 또는 Java : StringBuilder가있는 프리 엔드 문자열?
-
09-09-2019 - |
문제
나는 우리가 사용을 사용하여 끈을 추가 할 수 있다는 것을 알고 있습니다 StringBuilder
. 우리가 현을 선발 할 수있는 방법이 있습니까 (즉, 문자열 앞에서 줄을 추가) StringBuilder
따라서 우리는 성능 이점을 유지할 수 있습니다 StringBuilder
제안?
다른 팁
문자열을 선제하면 일반적으로 삽입 지점 후에는 백업 배열의 일부를 다시 복사해야하므로 끝까지 추가하는 것만 큼 빠르지 않습니다.
그러나 당신은 Java에서 이것을 할 수 있습니다 (c#에서는 동일하지만 메소드는 Insert
):
aStringBuilder.insert(0, "newText");
많은 Prepends가있는 고성능이 필요한 경우 자신의 버전을 작성해야합니다. StringBuilder
(또는 다른 사람을 사용하십시오). 표준으로 StringBuilder
(기술적으로 다르게 구현 될 수 있지만) 삽입 지점 후에 데이터 복사가 필요합니다. n 텍스트를 삽입하는 데 시간이 걸릴 수 있습니다.
순진한 접근 방식은 후원에 오프셋을 추가하는 것입니다. char[]
버퍼와 길이. Prepend를위한 공간이 충분하지 않으면 데이터를 엄격히 필요 이상으로 이동하십시오. 이것은 성능을 O (n log n)로 되돌릴 수 있습니다 (생각합니다). 보다 세련된 접근 방식은 버퍼를 순환시키는 것입니다. 그런 식으로 배열의 양쪽 끝에있는 여분의 공간이 인접 해집니다.
확장 방법을 시도 할 수 있습니다.
/// <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!
나는 그것을 사용하지 않았지만 자바를위한 로프 흥미로운 것 같습니다. 프로젝트 이름은 Words에서 Play입니다. 로프 대신 a 끈 진지한 작업을 위해. 선불 및 기타 운영에 대한 성과 페널티를 얻습니다. 당신이 이것을 많이하고 있다면 살펴볼 가치가 있습니다.
로프는 문자열의 고성능 대체물입니다. "로프 : 문자열 대안"에 자세히 설명 된 Datafrsucture는 Prepend, Append, Delete 및 Insert와 같은 일반적인 문자열 수정을 위해 String과 StringBuffer보다 비대칭 적으로 더 나은 성능을 제공합니다. 문자열과 마찬가지로 로프는 불변이기 때문에 멀티 스레드 프로그래밍에 사용하기에 적합합니다.
문자열을 역전시킨 다음 결과를 뒤집을 수 있습니다. O (n^2) 최악의 비용 대신 O (n) 비용이 발생합니다.
Java의 StringBuilder 클래스를 사용하여 Prepend를 원한다면 다음은 다음과 같습니다.
StringBuilder str = new StringBuilder();
str.Insert(0, "text");
내가 당신을 올바르게 이해한다면, 메소드를 삽입하십시오 원하는대로 할 것 같습니다. 오프셋 0에 문자열을 삽입하면됩니다.
사용해보십시오 끼워 넣다()
StringBuilder MyStringBuilder = new StringBuilder("World!");
MyStringBuilder.Insert(0,"Hello "); // Hello World!
다른 의견으로 판단하면이 작업을 수행하는 표준적인 빠른 방법은 없습니다. StringBuilder를 사용합니다 .Insert(0, "text")
고통스럽게 느린 문자열 연결 (> 100000 컨택트 기반)을 사용하는 것보다 약 1-3 배의 빠르기 때문에 아래는 잠재적으로 수천 번 더 빨리 수천 번 더 빠르게 전제하는 클래스입니다!
다른 기본 기능을 포함 시켰습니다 append()
, subString()
그리고 length()
추가 및 기간은 StringBuilder 추가보다 약 2 배 빠른 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)
}
}
간단한 클래스로 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 변수와 함께 Intelli-Sense를 사용할 때마다 Prepend 및 Prependline 메소드가 나타납니다. Prepend를 사용할 때는 추가하는 것보다 역 순서로 선정해야한다는 것을 기억하십시오.
이것은 작동해야합니다 :
aStringBuilder = "newText" + aStringBuilder;