2009-10-23 31 views
56

Estoy intentando truncar texto largo en C#, pero no quiero que mi cuerda se corte en parte a través de una palabra. ¿Alguien tiene una función que pueda usar para truncar mi cadena al final de una palabra?Truncar cadena en palabras enteras en .NET C#

por ejemplo:

"This was a long string..." 
No

:

"This was a long st..." 
+1

Podría dar la solución actual para truncar? – pyrocumulus

+2

@Cloud Just .Substring (0, ) – TimS

+2

Bueno, si es mayor que la cadena real, la subcadena arrojará una excepción, que requiere un control adicional. –

Respuesta

71

Gracias por su respuesta a Dave. He retocado la función un poco y esto es lo que estoy usando ... a menos que haya más comentarios;)

public static string TruncateAtWord(this string input, int length) 
{ 
    if (input == null || input.Length < length) 
     return input; 
    int iNextSpace = input.LastIndexOf(" ", length, StringComparison.Ordinal); 
    return string.Format("{0}...", input.Substring(0, (iNextSpace > 0) ? iNextSpace : length).Trim()); 
} 
+3

Además de esto, ahora también estoy llamando a otra función de utilidad de cadenas desde esta, que elimina cualquier etiqueta HTML (usando RegEx). Esto minimiza el riesgo de HTML roto como resultado del truncamiento, ya que todas las cadenas estarán en texto sin formato. – TimS

+7

Tenga en cuenta que este método busca el primer espacio * DESPUÉS * del valor de longitud especificado, lo que casi siempre hace que la cadena resultante sea más larga que el valor. Para encontrar el último espacio antes de la longitud, simplemente sustituya 'input.LastIndexOf (" ", length)' al calcular 'iNextSpace'. – CBono

+3

+100 para el comentario de CBono: ¡esto debe ser antes! ¡En el caso de que haya una gran cantidad de dinero en su moneda, tendrá todas las cuerdas que existen más allá de su longitud deseada! – Jason

81

intente lo siguiente. Es bastante rudimentario Solo encuentra el primer espacio comenzando en la longitud deseada.

public static string TruncateAtWord(this string value, int length) { 
    if (value == null || value.Length < length || value.IndexOf(" ", length) == -1) 
     return value; 

    return value.Substring(0, value.IndexOf(" ", length)); 
} 
+15

¡Perfecto! Y no una expresión regular a la vista :) – TimS

+5

¿Tendría sentido encontrar el primer espacio ANTES de la longitud deseada? De lo contrario, ¿tienes que adivinar cuál es la longitud deseada? – mlsteeves

+1

También debería ser -1 para no usar expresiones regulares;) – Goran

3

Si está utilizando formas de las ventanas, en el método Graphics.DrawString, hay una opción en StringFormat para especificar si la cadena debe ser truncado, si no cabe en el área especificada. Esto controlará la adición de puntos suspensivos según sea necesario.

http://msdn.microsoft.com/en-us/library/system.drawing.stringtrimming.aspx

+0

Esto es para una página ASP.Net, pero hago algunas cosas de Win Forms tan buenas de saber! – TimS

2

Tomé su enfoque un poco más lejos:

public string TruncateAtWord(string value, int length) 
{ 
    if (value == null || value.Trim().Length <= length) 
     return value; 

    int index = value.Trim().LastIndexOf(" "); 

    while ((index + 3) > length) 
     index = value.Substring(0, index).Trim().LastIndexOf(" "); 

    if (index > 0) 
     return value.Substring(0, index) + "..."; 

    return value.Substring(0, length - 3) + "..."; 
} 

I Estoy usando esto para truncar tweets.

5

Mi contribución:

public static string TruncateAtWord(string text, int maxCharacters, string trailingStringIfTextCut = "&hellip;") 
{ 
    if (text == null || (text = text.Trim()).Length <= maxCharacters) 
     return text; 

    int trailLength = trailingStringIfTextCut.StartsWith("&") ? 1 
                   : trailingStringIfTextCut.Length; 
    maxCharacters = maxCharacters - trailLength >= 0 ? maxCharacters - trailLength 
                : 0; 
    int pos = text.LastIndexOf(" ", maxCharacters); 
    if (pos >= 0) 
     return text.Substring(0, pos) + trailingStringIfTextCut; 

    return string.Empty; 
} 

Esto es lo que uso en mis proyectos, con final opcional. El texto nunca excederá los maxCharacters + longitud del texto final.

+0

+1 para el uso de & hellip; :) – manudea

1

simplificado, se agregó la opción de carácter de trunking y se convirtió en una extensión.

public static string TruncateAtWord(this string value, int maxLength) 
    { 
     if (value == null || value.Trim().Length <= maxLength) 
      return value; 

     string ellipse = "..."; 
     char[] truncateChars = new char[] { ' ', ',' }; 
     int index = value.Trim().LastIndexOfAny(truncateChars); 

     while ((index + ellipse.Length) > maxLength) 
      index = value.Substring(0, index).Trim().LastIndexOfAny(truncateChars); 

     if (index > 0) 
      return value.Substring(0, index) + ellipse; 

     return value.Substring(0, maxLength - ellipse.Length) + ellipse; 
    } 
+0

esto simplemente no funciona como se esperaba. Por favor, al menos haz un chequeo de cordura antes de publicar algo aquí. – avs099

0

Yo uso este

public string Truncate(string content, int length) 
    { 
     try 
     { 
      return content.Substring(0,content.IndexOf(" ",length)) + "..."; 
     } 
     catch 
     { 
      return content; 
     } 
    } 
1

Esto es lo que ocurrió. Esto es para obtener el resto de la oración también en fragmentos.

public static List<string> SplitTheSentenceAtWord(this string originalString, int length) 
    { 
     try 
     { 
      List<string> truncatedStrings = new List<string>(); 
      if (originalString == null || originalString.Trim().Length <= length) 
      { 
       truncatedStrings.Add(originalString); 
       return truncatedStrings; 
      } 
      int index = originalString.Trim().LastIndexOf(" "); 

      while ((index + 3) > length) 
       index = originalString.Substring(0, index).Trim().LastIndexOf(" "); 

      if (index > 0) 
      { 
       string retValue = originalString.Substring(0, index) + "..."; 
       truncatedStrings.Add(retValue); 

       string shortWord2 = originalString; 
       if (retValue.EndsWith("...")) 
       { 
        shortWord2 = retValue.Replace("...", ""); 
       } 
       shortWord2 = originalString.Substring(shortWord2.Length); 

       if (shortWord2.Length > length) //truncate it further 
       { 
        List<string> retValues = SplitTheSentenceAtWord(shortWord2.TrimStart(), length); 
        truncatedStrings.AddRange(retValues); 
       } 
       else 
       { 
        truncatedStrings.Add(shortWord2.TrimStart()); 
       } 
       return truncatedStrings; 
      } 
      var retVal_Last = originalString.Substring(0, length - 3); 
      truncatedStrings.Add(retVal_Last + "..."); 
      if (originalString.Length > length)//truncate it further 
      { 
       string shortWord3 = originalString; 
       if (originalString.EndsWith("...")) 
       { 
        shortWord3 = originalString.Replace("...", ""); 
       } 
       shortWord3 = originalString.Substring(retVal_Last.Length); 
       List<string> retValues = SplitTheSentenceAtWord(shortWord3.TrimStart(), length); 

       truncatedStrings.AddRange(retValues); 
      } 
      else 
      { 
       truncatedStrings.Add(retVal_Last + "..."); 
      } 
      return truncatedStrings; 
     } 
     catch 
     { 
      return new List<string> { originalString }; 
     } 
    } 
1

Esta solución funciona también (toma primeras 10 palabras de miCadena):

String.Join(" ", myString.Split(' ').Take(10)) 
Cuestiones relacionadas