2012-01-09 62 views
9

Estoy tratando de contar el número de palabras de un cuadro de texto enriquecido en C#, el código que tengo a continuación solo funciona si se trata de una sola línea. ¿Cómo hago esto sin confiar en Regex o cualquier otra función especial?Contando el número de palabras en C#

string whole_text = richTextBox1.Text; 
string trimmed_text = whole_text.Trim(); 
string[] split_text = trimmed_text.Split(' '); 
int space_count = 0; 
string new_text = ""; 

foreach(string av in split_text) 
{ 
    if (av == "") 
    { 
     space_count++; 
    } 
    else 
    { 
     new_text = new_text + av + ","; 
    } 
} 

new_text = new_text.TrimEnd(','); 
split_text = new_text.Split(','); 
MessageBox.Show(split_text.Length.ToString()); 
+5

He aquí una sugerencia para su preparación: mirar las [Líneas] (http://msdn.microsoft.com/en-us/library/system.windows. forms.textboxbase.lines.aspx) propiedad de RichTextBox para recuperar los contenidos de la RTB. –

Respuesta

15

Ya que sólo está interesado en Contar palabras, y que no se preocupan por las palabras individuales, String.Split podrían evitarse. String.Split es útil, pero genera innecesariamente un (potencialmente) gran cantidad de objetos String, lo que a su vez crea una carga innecesaria en el recolector de basura. Para cada palabra de su texto, se debe crear una instancia de un nuevo objeto String, y luego se recopilará pronto ya que no lo está usando.

Para una tarea, esto puede no importar, pero si el contenido de su cuadro de texto cambia a menudo y realiza este cálculo dentro de un controlador de eventos, puede ser más inteligente simplemente iterar manualmente entre caracteres. Si realmente quiere usar String.Split, entonces busque una versión más simple como Yonix recomendada.

De lo contrario, usar un algoritmo similar a esto:

var text = richTextBox1.Text.Trim(); 
int wordCount = 0, index = 0; 

while (index < text.Length) 
{ 
    // check if current char is part of a word 
    while (index < text.Length && !char.IsWhiteSpace(text[index])) 
     index++; 

    wordCount++; 

    // skip whitespace until next word 
    while (index < text.Length && char.IsWhiteSpace(text[index])) 
     index++; 
} 

Este código debe trabajar mejor con los casos en los que tiene múltiples espacios entre cada palabra.

0

Su enfoque está en el camino correcto. Haría algo así como pasar la propiedad de texto de richTextBox1 al método. Sin embargo, esto no será exacta si su rico cuadro de texto es el formato HTML, por lo que tendrá que se deben eliminar las etiquetas HTML antes de ejecutar el número de palabras:

public static int CountWords(string s) 
    { 
    int c = 0; 
    for (int i = 1; i < s.Length; i++) 
    { 
     if (char.IsWhiteSpace(s[i - 1]) == true) 
     { 
     if (char.IsLetterOrDigit(s[i]) == true || 
      char.IsPunctuation(s[i])) 
     { 
      c++; 
     } 
     } 
    } 
    if (s.Length > 2) 
    { 
     c++; 
    } 
    return c; 
} 
1

Tenga una mirada en la propiedad mencionada en Lines @ Jay Riggs comenta, junto con this overload of String.Split para hacer el código mucho más simple. Entonces, el enfoque más simple sería recorrer cada línea en la propiedad Lines, llamar al String.Split y agregar la longitud de la matriz a un conteo en ejecución.

EDITAR: Además, ¿hay algún motivo por el que esté utilizando un RichTextBox en lugar de un TextBox con Multiline establecido en True?

4

Hay algunas formas mejores de hacer esto, pero de acuerdo con lo que tienes, prueba lo siguiente:

string whole_text = richTextBox1.Text; 
string trimmed_text = whole_text.Trim(); 

// new line split here 
string[] lines = trimmed_text.Split(Environment.NewLine.ToCharArray()); 

// don't need this here now...    
//string[] split_text = trimmed_text.Split(' '); 

int space_count = 0; 
string new_text = ""; 

Ahora crea dos foreach. Uno para cada línea y otro para contar palabras dentro de las líneas.

foreach (string line in lines) 
{ 
    // Modify the inner foreach to do the split on ' ' here 
    // instead of split_text 
    foreach (string av in line.Split(' ')) 
    { 
     if (av == "") 
     { 
      space_count++; 
     } 
     else 
     { 
      new_text = new_text + av + ","; 
     } 
    } 
} 

new_text = new_text.TrimEnd(','); 

// use lines here instead of split_text 
lines = new_text.Split(','); 
MessageBox.Show(lines.Length.ToString()); 
} 
24
char[] delimiters = new char[] {' ', '\r', '\n' }; 
whole_text.Split(delimiters,StringSplitOptions.RemoveEmptyEntries).Length; 
+2

Esta sería la parte de "hay mejores formas de hacer esto" que mencioné en mi respuesta;) +1. –

+0

+1 para 'RemoveEmptyEntries'. Hace una diferencia si hay múltiples espacios en blanco en una fila. – Groo

2

Esta fue una pregunta de la entrevista de selección de teléfono que acabo de tomar (por una gran empresa ubicada en CA que vende todo tipo de dispositivos que comienza con una letra "i"), y creo que franqueado ... después de desconectarme, escribí esto. Ojalá pudiera hacerlo durante la entrevista ..

static void Main(string[] args) 
{ 
    Debug.Assert(CountWords("Hello world") == 2); 
    Debug.Assert(CountWords(" Hello world") == 2); 
    Debug.Assert(CountWords("Hello world ") == 2); 
    Debug.Assert(CountWords("Hello  world") == 2); 
} 

public static int CountWords(string test) 
{ 
    int count = 0; 
    bool wasInWord = false; 
    bool inWord = false; 

    for (int i = 0; i < test.Length; i++) 
    { 
     if (inWord) 
     { 
      wasInWord = true; 
     } 

     if (Char.IsWhiteSpace(test[i])) 
     { 
      if (wasInWord) 
      { 
       count++; 
       wasInWord = false; 
      } 
      inWord = false; 
     } 
     else 
     { 
      inWord = true; 
     } 
    } 

    // Check to see if we got out with seeing a word 
    if (wasInWord) 
    { 
     count++; 
    } 

    return count; 
} 
0

Se utilizó una forma adaptada de la respuesta de Yoshi, donde corrigió el problema en el que no contaría con la última palabra de una cadena si no había espacio en blanco después de que:

public static int CountWords(string test) 
{ 
    int count = 0; 
    bool inWord = false; 

    foreach (char t in test) 
    { 
    if (char.IsWhiteSpace(t)) 
    { 
     inWord = false; 
    } 
    else 
    { 
     if (!inWord) count++; 
     inWord = true; 
    } 
    } 
    return count; 
} 
0
public static int WordCount(string str) 
{   
    int num=0; 
    bool wasInaWord=true;; 

    if (string.IsNullOrEmpty(str)) 
    { 
     return num; 
    } 

    for (int i=0;i< str.Length;i++) 
    { 
     if (i!=0) 
     { 
      if (str[i]==' ' && str[i-1]!=' ') 
      { 
       num++; 
       wasInaWord=false; 
      } 
     } 
      if (str[i]!=' ') 
      { 
       wasInaWord=true;     
      } 
    } 
    if (wasInaWord) 
    { 
     num++; 
    } 
    return num; 
} 
+0

Proporcione alguna explicación para el código en su respuesta. –

-1

¡También puede hacerlo de esta manera! Agregue este método a sus métodos de extensión.

public static int WordsCount(this string str) 
    { 
     return Regex.Matches(str, @"((\w+(\s?)))").Count; 
    } 

Y llámalo así.

string someString = "Let me show how I do it!"; 
    int wc = someString.WordsCount(); 
+0

da una respuesta incorrecta si tenemos varios espacios o un salto de línea "\ r \ n" entre las palabras. – Artemious

0

Esto debería funcionar

input.Split(' ').ToList().Count; 
Cuestiones relacionadas