2010-04-30 6 views
17

Estoy escribiendo una función básica para convertir millones de nombres, en un proceso por lotes único, de su forma actual en mayúsculas a un caso mixto apropiado. Se me ocurrió la siguiente función:¿Cómo se puede mejorar este método para convertir un nombre al caso apropiado?

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:

  1. JOHN SMITH → John Smith
  2. Smith, John T → Smith, John T
  3. JOHN O'BRIAN → John O'Brian
  4. JOHN DOE-SMITH → John Doe-Smith

Hay algunos casos extremos que no funcionan:

  1. JASON MCDONALD → Jason McDonald (Correcto: Jason McDonald)
  2. OSCAR DE LA HOYA → Oscar de la Hoya (Correcto: Oscar de la Hoya)
  3. MARIE DIFRANCO → Marie Difranco (correcto: Marie DiFranco)

Estos no son capturados y no estoy seguro de si puedo h y todos estos casos de borde extraño. ¿Cómo puedo cambiar o agregar para capturar más casos extremos? Estoy seguro de que hay toneladas de casos extremos en los que ni siquiera estoy pensando. Toda la carcasa debe seguir las convenciones de América del Norte también, 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.

+0

Un poco de detalles menores, pero FxCop debería darle una advertencia sobre 'input.ToLower()'; debe especificar la cultura para usar allí también. No estoy seguro de si eso se aplica a 'Char.ToUpper' también. –

+0

Sé que esto no ayuda, pero ... Esta es una razón por la cual es importante tener buenos datos para empezar. Si los nombres se han almacenado con mayúsculas y minúsculas, es fácil ir a mayúsculas si es necesario. Del mismo modo, si tiene sus nombres divididos en primer/último, es fácil unirse cuando sea necesario, pero no tan fácil de revertir. –

+1

@Nelson, pero cuando no tienes control de dónde provienen los datos tienes que hacerlo :( – Kelsey

Respuesta

9

Creo que volverá a ejecutar una pared aquí porque normalmente no podrá juzgar correctamente si una conversión es razonable o no.

Tenga en cuenta sus casos extremos

JASON MCDONALD -> Jason McDonald (Correcto: Jason McDonald)

Usted podría simplemente comprobar si hay Mc al comienzo de su nombre y luego solicitar su corrección , ¿derecho? Pero, ¿y si su persona se llama Mcizck (lo hice por supuesto) y eso no debería corregirse a Mc Izck, pero 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 es realmente difícil de resolver, especialmente para una computadora. Las culturas son demasiado diferentes para ser modeladas correctamente. Incluso si dice que las convenciones de América del Norte tienen prioridad, tendrá un alto porcentaje de "falsos positivos". Nuestra sociedad consiste en una gran mezcla de culturas, simplemente no es adecuado decir "el norteamericano tiene prioridad".

Sin manejar las cajas de borde, supongo que su solución actual funcionará el 99% del tiempo. Todos los casos de bordes adicionales deben corregirse manualmente si se requieren nombres 100% correctos.

0

Bueno, en primer lugar, este código emitirá una excepción si el nombre tiene un 'o - al final, ya que tratará de poner en mayúscula el siguiente elemento (no existente) en la matriz. edición, véase el comentario a continuación

Aparte de eso ...

No creo que realmente puede dar cuenta de DiFranco menos que única cuenta para DiFranco y ningún otro Di 's (hay ¿alguna?). Además, creo que es seguro suponer que cualquier Mc merece una próxima carta de capital. Y también creo que es seguro decir que de y la cuando el espacio alrededor de ellos puede ser menor.

Pero al final del día, parece que está tratando de hacer uso de las culturas, lo que me indica que tal vez no solo está usando el inglés. Si este es el caso, entonces creo que vas a tener muchos más problemas de los que piensas. Si solo estás haciendo inglés (o este módulo es el módulo en inglés y hay otros para otros idiomas), entonces tal vez estés tan cerca como puedas (aparte de Mc, etc.)

+0

DiBella es otro 'Di' (buenos recuerdos de una chica con ese apellido de la escuela secundaria ;-)) – DaveDev

+1

@statichippo No creo que cause una excepción (simplemente lo probé), fíjate en el caso del bucle for 'i + 1 Kelsey

+0

woops, no se dieron cuenta de eso. editado – hackerhasid

0

Podrías

  • Split, en sus delimitadores "", "" y "-"
  • caso Título cada parte
  • manejar todas sus casos extremos de cada frase
3

no hay solución general a este problema. Incluso dentro de los casos de borde común como "Mc", hay ejemplos de contador. Tuve un amigo en la universidad con un nombre de "Mc" que no capitalizó el siguiente personaje; aparentemente fue arruinado en la inmigración hace generaciones y todos se quedan con la ortografía históricamente incorrecta.

Uno de los nombres de mi colega son dos nombres tradicionales CamelCased juntos. Nunca podrás dar cuenta de eso.

Este problema es equivalente al aumento de escala de un archivo de video; puede aproximarse lo mejor que puede, pero no puede generar mágicamente información que no se almacenó en primer lugar.

+3

¿Quiere decir que no puede "mejorar" y "acercar" automáticamente 100x en una imagen de baja calidad como lo hacen en la televisión? –

1

Puede crear reglas que lo acerquen, pero no puede obtener el 100%. Por ejemplo, puede crear una lista de prefijos (Mc, Di, etc.)

  1. Si el prefijo termina en una vocal y la siguiente letra es una vocal, en minúscula.
  2. Si el prefijo termina en una vocal y la siguiente letra es una consonante, mayúscula.
  3. Si el prefijo termina en una consonante, la siguiente letra es mayúscula.

Etc ... pero es probable que desee obtener una buena lista de los prefijos y siempre tendrá excepciones.

0

El problema es que, como todos los demás dijeron, nunca vas a atrapar cada caso extremo. Iba a sugerir ir here, descargar el conjunto completo de datos y comparar. Pero, ese conjunto de datos está en mayúsculas. Dado que este es un proceso de una sola vez, en su lugar, descargaría la lista del enlace mencionado anteriormente que tiene los 1000 apellidos principales, los corregiré manualmente y procesaré sus registros en esa lista. Marque esos registros no procesados ​​y vea si el número es lo suficientemente pequeño como para ser manejable a mano.

0

Su pregunta es si su programa puede ser mejorado. Mi respuesta es: "¿Qué dirección es la mejora?" Tienes dos casos de borde diferentes que son mutuamente excluyentes.O no atrapará a las personas con reglas de capitalización inusuales o no atrapará a las personas que no cumplan con las reglas de mayúsculas 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" es también un apellido de alguien allí. Entonces, si implementas un método para descapitalizar "de la", entonces extrañas a mi amigo y estaré triste. Y si no implementa la descapitalización, se pierde a esas otras personas. Y cielo no permita que se encuentre con algún De la Rosa que no sea atrapado por ningún método ...

Entonces piense, ¿qué dirección considera que es "mejora" para su código? Si considera que debe manejar los casos extremos por capitalización inusual y cuenta manualmente a aquellos que no respetan, las demás respuestas proporcionadas lo ayudarán a alcanzar ese objetivo. Si considera que debe manejar manualmente las mayúsculas inusuales, entonces su código no necesita cambios. De cualquier manera, tendrás que hacer algo manualmente.

4

Espero que la razón por la que está haciendo esta conversión es porque el software está cambiando para permitir a los usuarios ingresar 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. Luego 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 dejar que los usuarios actualicen sus propios nombres, el segundo método más confiable sería recopilar listas de (últimos) nombres de fuentes públicas. Si puede encontrar suficientes de estos, debería poder cubrir más casos extremos: simplemente vea si el nombre existe en su lista debidamente enmarcada, luego use esa carcasa.

+1

Es una migración de datos del sistema donde los "clientes" no tienen acceso a estos datos en los antiguos o nuevos. Solo una limpieza por lotes de datos antes de importarlos al nuevo sistema. – Kelsey

+1

+1 Lo importante es que debemos respetar los deseos del cliente sobre cómo se escriben o escriben en mayúscula sus nombres. –

+1

Si esto pretende ser una limpieza por lotes, no debe cambiar el caso en absoluto. Todos los topes en todos los casos implican que la información del caso no se conoce.Introducir la capitalización como relevante en realidad ensucia sus datos, porque pasa de 0% de errores de capitalización a> 0% de errores de capitalización. –

0
<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 
Cuestiones relacionadas