c# - diferente - ¿Cómo se puede mejorar este método para convertir un nombre a un caso adecuado?
string equals ignore case c# (9)
Creo que volverás a correr una pared aquí porque, por lo general, no podrás juzgar correctamente si una conversión es razonable o no.
Considere sus casos de borde
JASON MCDONALD -> Jason Mcdonald (Correcto: Jason McDonald)
Simplemente puede buscar a Mc al comienzo de su nombre y luego aplicar su corrección, ¿verdad? Pero, ¿qué pasa si su persona se llama Mcizck (yo inventé eso por supuesto) y eso no debería corregirse a Mc Izck sino que debería dejarse como está?
No hay una solución 100% perfecta para este problema. Lo que tienes aquí es un problema de lenguaje natural, y son realmente difíciles de resolver, especialmente para una computadora. Las culturas son demasiado diferentes para ser modeladas correctamente. Incluso si dice que las convenciones norteamericanas tienen prioridad, tendrá un alto porcentaje de "falsos positivos". Nuestra sociedad se compone de una gran mezcla de culturas, simplemente no es suficiente decir "América del Norte tiene prioridad".
Sin manejar los casos de borde, supongo que su solución actual funcionará el 99% del tiempo. Todos los casos adicionales deben corregirse manualmente si realmente se requieren nombres correctos al 100%.
Estoy escribiendo una función básica para convertir millones de nombres, en un proceso por lotes de una sola vez, de su actual forma en mayúsculas a un caso mixto adecuado. Se me ocurrió la siguiente función:
public string ConvertToProperNameCase(string input)
{
char[] chars = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(input.ToLower()).ToCharArray();
for (int i = 0; i + 1 < chars.Length; i++)
{
if ((chars[i].Equals(''/''')) ||
(chars[i].Equals(''-'')))
{
chars[i + 1] = Char.ToUpper(chars[i + 1]);
}
}
return new string(chars);
}
Funciona en la mayoría de los casos, tales como:
- JOHN SMITH → John Smith
- SMITH, JOHN T → Smith, John T
- JOHN O''BRIAN → John O''Brian
- JOHN DOE-SMITH → John Doe-Smith
Hay algunos casos de borde que no funcionan:
- JASON MCDONALD → Jason Mcdonald (Correcto: Jason McDonald)
- OSCAR DE LA HOYA → Oscar De La Hoya (Correcto: Oscar De La Hoya)
- MARIE DIFRANCO → Marie Difranco (Correcto: Marie DiFranco)
Estos no se capturan y no estoy seguro de si puedo manejar todos estos casos extraños. ¿Cómo puedo cambiar o agregar para capturar más casos de borde? Estoy seguro de que hay un montón de casos de borde en los que ni siquiera estoy pensando. Todas las carcasas deben seguir las convenciones de América del Norte, lo que significa que si ciertos países esperan un formato de capitalización diferente, entonces el formato de América del Norte tiene prioridad.
El problema es que, como todos los demás dijeron, nunca se va a detectar todos los casos de vanguardia. Iba a sugerir ir here , descargar el conjunto completo de datos y comparar. Pero, ese conjunto de datos es todo en mayúsculas. Como este es un proceso de una sola vez, en su lugar, descargaría la lista del enlace mencionado que tiene los 1000 mejores apellidos, los corregiría manualmente y procesaría sus registros con esa lista. Marque los registros que no se procesaron y vea si el número es lo suficientemente pequeño como para ser manejable a mano.
Espero que la razón por la que está haciendo esta conversión sea porque el software está cambiando para permitir que los usuarios ingresen sus nombres con la carcasa correcta en primer lugar.
Dicho esto, la única solución confiable sería notificar a los usuarios que ha cambiado la representación de su nombre. Entonces pueden editar la carcasa si es incorrecta. (Puede llamarlos, enviarlos por correo electrónico, esperar hasta que usen su software la próxima vez, etc.)
Si no puede permitir que los usuarios actualicen sus propios nombres, el segundo método más confiable sería recopilar listas de nombres (apellidos) de fuentes públicas. Si puede encontrar una cantidad suficiente de estos, debería poder cubrir más de los casos de borde: simplemente vea si el nombre existe en su lista de casillas adecuadas y luego use esa caja.
No hay una solución general para este problema. Incluso dentro de los casos comunes como "Mc", hay ejemplos contrarios. Tuve un amigo en la universidad con un nombre de "Mc" que no capitalizaba al siguiente personaje; al parecer, se cometió un error en la inmigración hace generaciones y todos se apegan a la ortografía oficial pero históricamente incorrecta.
Uno de los primeros nombres de mi colega es dos nombres tradicionales, CamelCased juntos. Nunca vas a poder dar cuenta de eso.
Este problema es equivalente a escalar un archivo de video; puede aproximarse a lo mejor que puede, pero no puede generar mágicamente información que no se almacenó en primer lugar.
Puedes crear reglas que te puedan acercar, pero no puedes obtener el 100%. Por ejemplo, puede crear una lista de prefijos (Mc, Di, etc.)
- Si el prefijo termina en una vocal y la siguiente letra es una vocal, en minúscula.
- Si el prefijo termina en una vocal y la siguiente letra es una consonante, en mayúsculas.
- Si el prefijo termina en una consonante, la siguiente letra es mayúscula.
Etc ... pero probablemente querrá obtener una buena lista de los prefijos y siempre tendrá excepciones.
Su pregunta es sobre si su programa puede ser mejorado. Mi respuesta es: "¿Qué dirección es la mejora?" Tiene dos casos de borde diferentes que son mutuamente excluyentes. O no capturará a las personas con reglas de capitalización inusuales, o no capturará a las personas que no cumplan con reglas de capitalización inusuales.
Fui a la escuela con alguien con un apellido de "De La Rosa". Teniendo en cuenta su ejemplo de de la Hoya, sería justo suponer que "de la Rosa" también es el apellido de alguien por ahí. Entonces, si implementas un método para descapitalizar "de la", entonces extrañas a mi amigo y estaremos tristes. Y si no implementas la descapitalización, pierdes a esas otras personas. Y el cielo no permita que te encuentres con algún De la Rosa que no sería atrapado por ninguno de los dos métodos ...
Entonces, piense, ¿qué dirección considera que es la "mejora" de su código? Si considera que debe manejar los casos perimetrales para el uso de mayúsculas inusuales y contabilizar manualmente a los que no cumplen, las otras respuestas proporcionadas lo ayudarán a alcanzar ese objetivo. Si considera que debería manejar manualmente el uso de mayúsculas inusuales, entonces su código no necesita cambios. De cualquier manera, tendrás que estar haciendo algo manualmente.
Tú podrías
- Dividir en sus delimitadores "", "," y "-"
- Titulo de caso cada parte
- Maneja todos tus casos de borde para cada frase
Bueno, en primer lugar, este código lanzará una excepción si el nombre tiene un ''o - al final, ya que intentará capitalizar el siguiente elemento (no existente) en la matriz. editar, ver comentario abajo
Aparte de eso...
No creo que realmente puedas dar cuenta de DiFranco a menos que solo tengas una cuenta de DiFranco y no de otras Di (¿hay alguna?). Además, creo que es seguro asumir que cualquier Mc merece una próxima letra mayúscula. Y también creo que es seguro decir que de y la cuando el espacio alrededor de ellos puede estar en mayúsculas.
Pero al final del día, parece que estás tratando de hacer uso de las culturas, lo que me indica que quizás no solo estás usando el inglés. Si este es el caso, entonces creo que vas a tener muchos más problemas de los que crees. Si solo estás haciendo inglés (o este módulo es el módulo de inglés y hay otros para otros idiomas), entonces quizás estés lo más cerca que puedas (aparte de Mc, etc.)
<System.Runtime.CompilerServices.Extension()> _
Public Function ProperCase(ByVal value As String) As String
If String.IsNullOrWhiteSpace(value) Then
Return String.Empty
End If
value = value.Trim
Dim sb As New StringBuilder(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower))
''// Special cases '' and -
For i As Integer = 0 To sb.Length
Dim c As Char = sb(i)
If sb(i).Equals("''") Or sb(i).Equals("-") Then
''Upper Case Next character
sb(i + 1) = Char.ToUpper(sb(i + 1))
End If
Next
If sb.ToString.StartsWith("Mac") Then
sb(3) = Char.ToUpper(sb(3))
End If
If sb.ToString.StartsWith("Mc") Then
sb(2) = Char.ToUpper(sb(2))
End If
Return sb.ToString
End Function