2010-11-30 30 views
16

Necesito tomar una cadena y ponerle mayúsculas a las palabras. Algunas palabras ("en", "en", etc.) no están en mayúscula y se cambian a minúsculas si se encuentran. La primera palabra siempre debe estar en mayúscula. Los apellidos como "McFly" no están en el alcance actual, por lo que la misma regla se aplicará a ellos, solo la primera letra en mayúscula.Capitalizar palabras en una cadena usando C#

Por ejemplo: "de ratones y hombres por CNN" debería cambiarse a "De ratones y hombres por CNN". (Por lo tanto ToTitleString no funcionará aquí)

Me pregunto cuál sería la mejor manera de hacerlo. Lo que pensé es dividir la cuerda por espacios, y revisar cada palabra, cambiarla si es necesario y concatenarla a la palabra anterior, y así sucesivamente. Parece bastante ingenuo y me preguntaba si hay una mejor manera de hacerlo, usando .Net 3.5.

+1

¿Qué es ToTitleString? –

+0

¿Cómo debe entender el programa que la CNN debe permanecer en mayúsculas? –

+3

@Chris: ¿Creo que quiere decir ToTitleCase ...? Vea aquí http://msdn.microsoft.com/en-us/library/system.globalization.textinfo.totitlecase.aspx y 'comentarios' de por qué no es aplicable. –

Respuesta

13

Dependiendo de la frecuencia con la que planee realizar las mayúsculas, me gustaría ir con el enfoque ingenuo. Podrías hacerlo con una expresión regular, pero el hecho de que no quieras poner en mayúsculas ciertas palabras lo hace un poco más complicado.

Editar:

Puede hacerlo con dos pasadas utilizando expresiones regulares

var result = Regex.Replace("of mice and men isn't By CNN", @"\b(\w)", m => m.Value.ToUpper()); 
result = Regex.Replace(result, @"(\s(of|in|by|and)|\'[st])\b", m => m.Value.ToLower(), RegexOptions.IgnoreCase); 

Esto da salida a Of Mice and Men Isn't by CNN.

La primera expresión pone en mayúscula cada letra en un límite de palabra y la segunda descarta cualquier palabra que coincida con la lista que está rodeada por espacios en blanco.

Las desventajas de este enfoque es que está utilizando expresiones regulares (ahora tiene dos problemas) y deberá mantener actualizada esa lista de palabras excluidas. Mi regex-fu no es lo suficientemente bueno para poder hacerlo en una expresión, pero podría ser posible.

+1

Esto tiene un pequeño error. Para una cadena como "Lo de Tom", el resultado es "cosa de Tom". – TMC

+0

@TMC, publique la solución –

0

Debe crear su propia función como la que describe.

0

La solución obvia más fácil (para las oraciones en inglés) sería:

  • "sentence".Split(" ") la frase sobre los caracteres de espacio
  • bucle a través de cada elemento
  • en mayúscula la primera letra de cada elemento - item[i][0].ToUpper(),
  • Vuelva a sumergir en una cuerda unida en un espacio.
  • Repita este proceso con "." y "," usando esa nueva cadena.
12

Uso

Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase("of mice and men By CNN"); 

a convertirse al caso adecuado y luego puede recorrer a través de las palabras clave a medida que se han mencionado.

+0

Esto está cerca, pero si observa el ejemplo del OP, el "Y" no debe escribirse en mayúscula. Pero este podría ser el primer paso en el algoritmo. ¿Realiza la conversión de ToTitleCase y busca palabras de casos especiales basadas en un diccionario y las revierte a minúsculas? –

1

Puede tener un diccionario con las palabras que desea ignorar, dividir la oración en frases (.split ('')) y para cada frase, verificar si la frase existe en el diccionario, si no lo hace, coloque mayúscula en el primer carácter y luego, agregue la cadena a un búfer de cadena. Si la frase que está procesando actualmente está en el diccionario, simplemente agréguela al búfer de cadenas.

0

Un enfoque no-inteligente que maneja el caso sencillo:

var s = "of mice and men By CNN"; 
var sa = s.Split(' '); 
for (var i = 0; i < sa.Length; i++) 
    sa[i] = sa[i].Substring(0, 1).ToUpper() + sa[i].Substring(1); 
var sout = string.Join(" ", sa); 
Console.WriteLine(sout); 
3

Por qué no usar ToTitleCase() primero y luego mantener una lista de palabras aplicables y Replace de nuevo a la versión totalmente minúscula de esas palabras aplicables (siempre que esa lista sea pequeña).

La lista de palabras aplicables se puede mantener en un diccionario y se puede pasar bastante eficientemente, reemplazando con el equivalente .ToLower().

+1

Sé que la respuesta es antigua, pero ToTitleCase() ya no existe en .NET Windows Store. Necesitará confiar solo en ToUpper() y posiblemente en algunos Regex para futuras aplicaciones. –

2

intentar algo como esto:

public static string TitleCase(string input, params string[] dontCapitalize) { 
    var split = input.Split(' '); 
    for(int i = 0; i < split.Length; i++) 
     split[i] = i == 0 
      ? CapitalizeWord(split[i]) 
      : dontCapitalize.Contains(split[i]) 
      ? split[i] 
      : CapitalizeWord(split[i]); 
    return string.Join(" ", split); 
} 
public static string CapitalizeWord(string word) 
{ 
    return char.ToUpper(word[0]) + word.Substring(1); 
} 

Más tarde puede actualizar el método CapitalizeWord si usted necesita para manejar apellidos complejos. Añadir esos métodos a una clase y utilizar de esta manera:

SomeClass.TitleCase("a test is a sentence", "is", "a"); // returns "A Test is a Sentence" 
+3

Terninos anidados santos. – jonnii

5

Aquí está la respuesta How to Capitalize names

CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture; 
TextInfo textInfo = cultureInfo.TextInfo; 

Console.WriteLine(textInfo.ToTitleCase(title)); 
Console.WriteLine(textInfo.ToLower(title)); 
Console.WriteLine(textInfo.ToUpper(title)); 
1

una ligera mejora en la respuesta de jonnii:

var result = Regex.Replace(s.Trim(), @"\b(\w)", m => m.Value.ToUpper()); 
     result = Regex.Replace(result, @"\s(of|in|by|and)\s", m => m.Value.ToLower(), RegexOptions.IgnoreCase); 
     result = result.Replace("'S", "'s"); 
Cuestiones relacionadas