2010-09-03 8 views
21

Tengo una instancia StringBuilder donde estoy haciendo numeroso sb.AppendLine("test"); por ejemplo.¿Cómo recuperar un recuento de líneas de StringBuilder?

¿Cómo puedo calcular cuántas líneas tengo?

Veo que la clase tiene .Length pero eso me dice cuántos caracteres hay en total.

¿Alguna idea?

+0

¿Ha considerado contar los saltos de línea? –

+0

El único problema con el recuento de saltos de línea es que StringBuilder no tiene métodos de buscar/indexar: necesita usar la propiedad indexada de Chars o contar en la cadena resultante (ToString()). Ambos pueden ser ineficientes si necesita contar la línea repetidamente. – VinayC

+1

Jon, hay una serie de soluciones muy obvias para esto; ¿Podría dar contexto para explicar por qué estas soluciones no son viables para usted? – tenfour

Respuesta

22

Ordenada por la eficiencia:

  1. Contando su AppendLine() llama a
  2. Calling IndexOf() en un bucle
  3. Uso de Regex
  4. Uso de String.Split()

El último es extraordinariamente caro y genera lotes de basura, no lo use.

+7

Creo que la opción n. ° 1 puede generar errores, ya que no garantiza que las llamadas a AppendLine() contasen realmente con el recuento real de nuevas líneas. Las otras opciones tienen un sentido eminente. – code4life

+1

Meh, las líneas nuevas no caen del cielo. Pero sí, la eficiencia está arriesgando el mantenimiento aquí. –

+8

no pueden caer del cielo pero pueden venir de 'Environment.NewLine',' \ r \ n', '\ n', o incluso del contenido que se pasa a uno de los otros métodos. –

2

Debe poder buscar el número de ocurrencias de \ n en la cadena.

ACTUALIZACIÓN: Una forma podría ser dividido en el carácter de nueva línea y contar el número de elementos en la matriz de la siguiente manera:

sb.ToString().Split('\n').length; 
+0

Sin duda funcionará, pero no es una buena solución si necesita recuento de líneas repetidamente. Por supuesto, Jon no ha mencionado si lo quiere una o más veces. – VinayC

+0

@VninayC - sí, fue una idea sobre cómo hacerlo, no me gustó desde el principio, ya que tienes que hacer un ToString() para hacer cualquier cosa. Definitivamente, si quisieras hacerlo varias veces envolverlo en algo que mantuviera un conteo en sí mismo sería lo mejor. –

18

Usted puede envolver StringBuilder con su propia clase que mantener un recuento de líneas a medida que se agregan o podría el número de '\ n' después de que su constructor esté lleno.

Regex.Matches(builder.ToString(), Environment.NewLine).Count 
+1

+1 propia clase, o tal vez incluso un método de extensión. – user7116

+4

Supongo que se refería a Regex.Matches (builder.ToString(), Environment.NewLine) .Count; porque Match() devuelve solo una coincidencia. – alex440

0

Realice una expresión regular para contar el número de terminadores de línea (por ejemplo, \ r \ n) en la cadena. O bien, cargar las cadenas en un cuadro de texto y hacer un recuento de líneas, pero esa es la forma en truco-ey de hacerlo

4

Prueba esto:

sb.ToString().Split(System.Environment.NewLine.ToCharArray()).Length; 
+2

Umm ... este código cuenta dos veces las líneas ... por ejemplo 3 líneas de sb.AppendLine ("a"); dará como resultado 7, no 3 ...! – code4life

+0

@ code4life Sí (por supuesto, depende de la "Longitud" de la cadena 'NewLine' en el sistema en cuestión). –

0

Se puede dividir la cadena Bulider datos en Array cadena [] y luego use String []. Length para el número de líneas.

algo así como a continuación:

String[] linestext = sb.Split(newline) 
Console.Writeline(linetext.Length) 
1

concluir cuál es su propia línea contando StringBuilder donde AppendLine ups un recuento de línea interna y proporciona un método para obtener el valor del número de líneas.

6

Puede crear una clase contenedora hacer lo siguiente:

public class Wrapper 
{ 
    private StringBuilder strBuild = null; 
    private int count = 0; 
    public Wrapper(){ 
     strBuild = new StringBuilder(); 
    } 
    public void AppendLine(String toAppendParam){ 
     strBuild.AppendLine(toAppendParam); 
     count++; 
    } 
    public StringBuilder getStringBuilder(){ 
     return strBuild; 
    } 

    public int getCount(){ 
     return count; 
    } 
} 
+3

Se corrigió el formato del código, pero es posible que desee cambiar esto para que sea más idiomático que C# en lugar de Java. – user7116

2

ACTUALIZACIÓNWhat Gabe said

b.ToString(). Count (c => c == '\ n') funcionaría también en este caso, y tal vez no ser mucho menos eficiente (aparte de la creación una copia separada de la cadena !).


una manera mejor, más rápido que la creación de una cadena de la StringBuilder y la división de ella (o la creación de la cadena y regex ing ella), es mirar en el StringBuilder y contar el número de '\n' caracteres no en.

El siguiente método de extensión enumerará a través de los caracteres en el generador de cadenas, luego puede linq hasta que su corazón esté satisfecho.

public static IEnumerable<char> GetEnumerator(this StringBuilder sb) 
    { 
     for (int i = 0; i < sb.Length; i++) 
      yield return sb[i]; 
    } 

... usa aquí, el recuento será 4

 StringBuilder b = new StringBuilder(); 
     b.AppendLine("Hello\n"); 
     b.AppendLine("World\n"); 

     int lineCount = b.GetEnumerator().Count(c => c =='\n'); 

+0

'b.ToString(). Count (c => c == '\ n')' funcionaría aquí también, y podría no ser mucho menos eficiente (¡además de crear una copia separada de la cadena!). – Gabe

+0

@Gabe: Debería haber sabido 'b.ToString(). Count (c => c == '\ n')' toma aproximadamente 2/3 del tiempo que hace mi enumerador. –

2

Si usted va a utilizar String.split(), que se necesitan para dividir la cadena con algunas opciones De esta manera:

static void Main(string[] args) 
{ 
    var sb = new StringBuilder(); 
    sb.AppendLine("this"); 
    sb.AppendLine("is"); 
    sb.AppendLine("a"); 
    sb.AppendLine("test"); 

    // StringSplitOptions.None counts the last (blank) newline 
    // which the last AppendLine call creates 
    // if you don't want this, then replace with 
    // StringSplitOptions.RemoveEmptyEntries 
    var lines = sb.ToString().Split(
     new string[] { 
      System.Environment.NewLine }, 
     StringSplitOptions.None).Length; 

    Console.WriteLine("Number of lines: " + lines); 

    Console.WriteLine("Press enter to exit."); 
    Console.ReadLine(); 
} 

Esto se traduce en:

Number of lines: 5

Cuestiones relacionadas