2009-04-10 13 views
82

Sé que podemos agregar cadenas usando StringBuilder. ¿Hay alguna manera de preinstalar cadenas (es decir, agregar cadenas delante de una cadena) usando StringBuilder para que podamos mantener los beneficios de rendimiento que StringBuilder ofrece?C# o Java: ¿Prefijo cadenas con StringBuilder?

+0

No entiendo su pregunta –

+5

Anteponer. La palabra es preceder. Preapendiendo una cadena debe ser algo así como agregar a ambos extremos de una cadena a la vez, supongo? –

Respuesta

119

Usar el método de inserción con el parámetro de posición establecido en 0 sería lo mismo que anteponer (es decir, insertar al principio).

Funciona tanto para C# y Java

+7

Insertar StringBuilder para Java: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html#insert(int,%20boolean) –

+0

El JavaDoc correcto para la API relevante es : http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html#insert(int,%20java.lang.CharSequence%29 – ArtB

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

Editar: Código formateado

2

Trate de usar Insert()

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

agregar el prefijo a una cadena requerirá generalmente copiar todo después del punto de inserción hacia la espalda alguna en la matriz de respaldo, por lo que no será tan rápido como agregarlo al final.

Pero puede hacerlo de esta manera en Java (en C# que es el mismo, pero el método se llama Insert):

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

Si he entendido bien, la insert method parece que va a hacer lo usted quiere. Sólo tiene que insertar la cadena en desplazamiento 0.

5

usted podría intentar un método de extensió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! 
10

Si requiere un alto rendimiento con una gran cantidad de antepone, que necesita para escribir su propia versión de StringBuilder (o uso de alguien más). Con el estándar StringBuilder (aunque técnicamente podría implementarse de manera diferente), insertar requiere copiar datos después del punto de inserción. Insertar n trozo de texto puede tomar O (n^2) tiempo.

Un enfoque ingenuo sería agregar un desplazamiento en la memoria intermedia char[] así como la longitud. Cuando no hay espacio suficiente para un antecedente, mueva los datos hacia arriba más de lo estrictamente necesario. Esto puede devolver el rendimiento a O (n log n) (creo). Un enfoque más refinado es hacer que el buffer sea cíclico. De esa forma, el espacio libre en ambos extremos de la matriz se vuelve contiguo.

5

No lo he usado pero Ropes For Java Sonidos intrigantes. El nombre del proyecto es un juego de palabras, use una cuerda en lugar de una Cadena para un trabajo serio. Obtiene la penalización de rendimiento para las operaciones de antependencia y otras operaciones. Vale la pena mirar, si vas a hacer mucho de esto.

Una cuerda es un reemplazo de alto rendimiento para cuerdas. La estructura de datos , descrito en detalle en "cuerdas: una alternativa para Strings", proporciona asintóticamente mejor rendimiento que tanto de cadena y StringBuffer para cadena común modificaciones como prepend, añadir, eliminar e insertar. Al igual que Strings, las cuerdas son inmutables y, por lo tanto, son adecuadas para su uso en la programación de múltiples hilos .

5

Puede construir la cuerda en reversa y luego invertir el resultado. Usted incurre en un costo de O (n) en lugar de un costo de O (n^2) en el peor de los casos.

+2

Eso solo funciona si va a agregar un individuo De lo contrario, tendrías que invertir cada cadena que añadiste, lo que consumiría casi todos los ahorros, dependiendo del tamaño y del número de cadenas. – ArtB

2

A juzgar por los otros comentarios, no hay una manera estándar rápida de hacerlo. Usar .Insert(0, "text") de StringBuilder es aproximadamente de solo 1-3 veces más rápido que usar una concatenación de cadenas dolorosamente lenta (basada en> 10000 concats), por lo que a continuación hay una clase para anteponer potencialmente miles de veces más rápido.

he incluido alguna otra funcionalidad básica como append(), subString() y length() etc. Ambos APPENDs y antepone varían desde alrededor de dos veces más rápido hasta 3 veces más lento que StringBuilder añade. Al igual que StringBuilder, el búfer en esta clase aumentará automáticamente cuando el texto se desborde del antiguo tamaño del búfer.

El código ha sido probado bastante, pero no puedo garantizar que esté libre de errores.

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

Esto debería funcionar:

aStringBuilder = "newText" + aStringBuilder; 
+0

En .NET, esto funciona perfectamente con los valores de tipo 'cadena', pero no funciona con valores de tipo 'StringBuilder'. La respuesta de @ScubaSteve funciona bien. – Contango

1

Se puede crear una extensión para StringBuilder sí mismo con una clase simple:

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

A continuación, sólo tiene que añadir:

using Application.Code.Helpers; 

Al inicio de cualquier clase que quieras usar StringBuilder in y en cualquier momento que use intelli-sense con una variable StringBuilder, aparecerán los métodos Prepend y PrependLine. Solo recuerde que cuando usa Prefijo, deberá Preceder en orden inverso al que tenía al Anexar.

Cuestiones relacionadas